/******************************************************************************
 * Name         : icvt_c10.c
 * Title        : UNIFLEX-to-intermediate code conversion for C10 data format
 * Created      : July 2006
 *
 * Copyright    : 2002-2008 by Imagination Technologies Limited.
 *              : All rights reserved. No part of this software, either
 *              : material or conceptual may be copied or distributed,
 *              : transmitted, transcribed, stored in a retrieval system or
 *              : translated into any human or computer language in any form
 *              : by any means, electronic, mechanical, manual or otherwise,
 *              : or disclosed to third parties without the express written
 *              : permission of Imagination Technologies Limited,
 *              : Home Park Estate, Kings Langley, Hertfordshire,
 *              : WD4 8LZ, U.K.
 *
 *
 * Modifications:-
 * $Log: icvt_c10.c $
 *****************************************************************************/

#include "uscshrd.h"
#include "bitops.h"
#include <limits.h>

IMG_INTERNAL
IMG_UINT32 GetInputToU8C10IntermediateSwizzle(PINTERMEDIATE_STATE	psState)
/*****************************************************************************
 FUNCTION	: GetInputToU8C10IntermediateInputSwizzle

 PURPOSE	: Get the swizzle to convert between data in the input channel order
			  and data in the intermediate U8/C10 channel order.

 PARAMETERS	: psState				- Compiler state.

 RETURNS	: The swizzle in the input format.
*****************************************************************************/
{
	PVR_UNREFERENCED_PARAMETER(psState);

	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if (psState->psTargetFeatures->ui32Flags2 & SGX_FEATURE_FLAGS2_USE_C10U8_CHAN_ORDER_RGBA)
	{
		return UFREG_SWIZ_RGBA;
	}
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	{
		return UFREG_SWIZ_BGRA;
	}
}

IMG_INTERNAL
IMG_UINT32 ConvertInputWriteMaskToIntermediate(PINTERMEDIATE_STATE	psState,
											   IMG_UINT32			uInputWriteMask)
/*****************************************************************************
 FUNCTION	: ConvertInputWriteMaskToIntermediate

 PURPOSE	: Convert the write mask for an input instruction to the right
			  channel order for a C10/U8 intermediate

 PARAMETERS	: psState				- Compiler state.
			  uInputWriteMask		- Input write mask.

 RETURNS	: The converted write mask.
*****************************************************************************/
{
	PVR_UNREFERENCED_PARAMETER(psState);

	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if (psState->psTargetFeatures->ui32Flags2 & SGX_FEATURE_FLAGS2_USE_C10U8_CHAN_ORDER_RGBA)
	{
		return uInputWriteMask;
	}
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	{
		return g_puSwapRedAndBlueMask[uInputWriteMask];
	}
}

IMG_INTERNAL
IMG_UINT32 ConvertInputChannelToIntermediate(PINTERMEDIATE_STATE	psState,
											 IMG_UINT32				uInputChan)
/*****************************************************************************
 FUNCTION	: ConvertInputChannelToIntermediate

 PURPOSE	: Convert input instruction channel select to the right
			  channel order for a C10/U8 intermediate instruction.

 PARAMETERS	: psState			- Compiler state.
			  uInputChan		- Input channel.

 RETURNS	: The converted channel.
*****************************************************************************/
{
	PVR_UNREFERENCED_PARAMETER(psState);

	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if (psState->psTargetFeatures->ui32Flags2 & SGX_FEATURE_FLAGS2_USE_C10U8_CHAN_ORDER_RGBA)
	{
		return uInputChan;
	}
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	{
		return g_puSwapRedAndBlueChan[uInputChan];
	}
}

static IMG_VOID ConvertDestinationC10(PINTERMEDIATE_STATE psState, 
									  PCODEBLOCK psCodeBlock, 
									  PUNIFLEX_INST psInputInst,
									  PUF_REGISTER psInputDest)
/*****************************************************************************
 FUNCTION	: ConvertDestinationC10

 PURPOSE	: Do conversion for a destination register which is always in F32 format.

 PARAMETERS	: psState				- Compiler state.
			  psCodeBlock			- Code block to insert any extra instructions needed.
			  psDest				- Destination register in the input format.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32		uChan;

	ASSERT(psInputDest->eType == UFREG_TYPE_VSOUTPUT);

	/*
		Add instructions to convert the C10/U8 result generated by the preceeding
		instructions back into the expected F32 destination registers.

		NB: USC_TEMPREG_CVTDSTOUT is used as the temporary destination for
			instructions that write to PS output colour (non-packed) and depth
			and VS outputs. All these are shader results are expected to be
			in F32 format.
	*/

	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if (psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_VEC34)
	{
		PINST	psConvertInst;

		psConvertInst = AllocateInst(psState, NULL);

		if (psInputDest->eFormat == UF_REGFORMAT_C10)
		{
			SetOpcode(psState, psConvertInst, IVPCKFLTC10);
		}
		else
		{
			ASSERT(psInputDest->eFormat == UF_REGFORMAT_U8);
			SetOpcode(psState, psConvertInst, IVPCKFLTU8);
		}

		GetDestinationF32_Vec(psState, psInputDest, &psConvertInst->asDest[0]);

		psConvertInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psInputInst->sDest.u.byMask);

		psConvertInst->u.psVec->bPackScale = IMG_TRUE;

		psConvertInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
		psConvertInst->asArg[0].uNumber = USC_TEMPREG_CVTC10DSTOUT;
		psConvertInst->asArg[0].eFmt = psInputDest->eFormat;

		psConvertInst->u.psVec->aeSrcFmt[0] = UF_REGFORMAT_C10;
		psConvertInst->u.psVec->auSwizzle[0] = ConvertSwizzle(psState, GetInputToU8C10IntermediateSwizzle(psState));

		AppendInst(psState, psCodeBlock, psConvertInst);

		StoreDestinationF32(psState, psCodeBlock, psInputInst, &psInputInst->sDest, USC_TEMPREG_CVTVECF32DSTOUT);
	}
	else
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	{
		PVR_UNREFERENCED_PARAMETER(psInputInst);

		for (uChan = 0; uChan < 4; uChan++)
		{
			PINST	psPackInst;
	
			if ((psInputDest->u.byMask & (1U << uChan)) == 0)
			{
				continue;
			}

			psPackInst = AllocateInst(psState, IMG_NULL);
			if (psInputDest->eFormat == UF_REGFORMAT_U8)
			{
				SetOpcode(psState, psPackInst, IUNPCKF32U8);
			}
			else
			{
				SetOpcode(psState, psPackInst, IUNPCKF32C10);
			}
			psPackInst->u.psPck->bScale = IMG_TRUE;
			GetDestinationF32(psState, psCodeBlock, psInputDest, uChan, &psPackInst->asDest[0]);
			psPackInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
			psPackInst->asArg[0].uNumber = USC_TEMPREG_CVTC10DSTOUT;
			SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uChan));
			psPackInst->asArg[0].eFmt = UF_REGFORMAT_C10;
			if (psInputDest->eFormat == UF_REGFORMAT_U8)
			{
				psPackInst->asArg[0].eFmt = UF_REGFORMAT_U8;
			}
			AppendInst(psState, psCodeBlock, psPackInst);
		}
	}
}

static IMG_UINT32 ConvertTempRegisterNumberC10(PINTERMEDIATE_STATE	psState,
											   PUF_REGISTER			psRegister)
/*****************************************************************************
 FUNCTION	: ConvertTempRegisterNumberC10
    
 PURPOSE	: Convert an input temporary register to a temporary register
			  number in the intermediate format..

 PARAMETERS	: psRegister					- The input register.
			  
 RETURNS	: The converted number.
*****************************************************************************/
{
	IMG_UINT32	uRegNum;
	
	ASSERT(psRegister->uNum < psState->uInputTempRegisterCount);
	uRegNum = USC_TEMPREG_MAXIMUM + psRegister->uNum * CHANNELS_PER_INPUT_REGISTER;
	ASSERT(uRegNum < psState->uNumRegisters);

	return uRegNum;
}

static IMG_VOID GetDestinationC10(PINTERMEDIATE_STATE psState, PUF_REGISTER psDest, PARG psHwSource)
/*****************************************************************************
 FUNCTION	: GetDestinationC10

 PURPOSE	: Convert a destination register in the input format into the intermediate format.

 PARAMETERS	: psState				- Compiler state.
			  psCodeBlock			- Code block to insert any extra instructions needed.
			  psDest				- Destination register in the input format.
			  psHwSource			- Pointer to the structure to fill out with the register in
									  the intermediate format.

 RETURNS	: None.
*****************************************************************************/
{
	InitInstArg(psHwSource);

	if (psDest->eType == UFREG_TYPE_PSOUTPUT)
	{
		ConvertPixelShaderResultArg(psState, psDest, psHwSource);
		psHwSource->eFmt = psDest->eFormat;
	}
	else if (psDest->eType == UFREG_TYPE_VSOUTPUT)
	{
		psHwSource->uType = USEASM_REGTYPE_TEMP;
		psHwSource->uNumber = USC_TEMPREG_CVTC10DSTOUT;
		if(psDest->eFormat == UF_REGFORMAT_U8)
		{
			psHwSource->eFmt = UF_REGFORMAT_U8;
		}
		else
		{
			psHwSource->eFmt = UF_REGFORMAT_C10;
		}
	}
	else if (psDest->eType == UFREG_TYPE_INDEXABLETEMP)
	{
		psHwSource->uType = USEASM_REGTYPE_TEMP;
		psHwSource->uNumber = USC_TEMPREG_C10INDEXTEMPDEST;
		psHwSource->eFmt = UF_REGFORMAT_C10;
	}
	else
	{
		ASSERT(psDest->eType == UFREG_TYPE_TEMP);
		ASSERT(psDest->eFormat == UF_REGFORMAT_U8 || psDest->eFormat == UF_REGFORMAT_C10);

		if (psDest->eRelativeIndex != UFREG_RELATIVEINDEX_NONE)
		{
			imgabort();
		}
		psHwSource->uType = USEASM_REGTYPE_TEMP;
		psHwSource->uNumber = ConvertTempRegisterNumberC10(psState, psDest);
		if (psDest->eFormat == UF_REGFORMAT_U8)
		{
			psHwSource->eFmt = UF_REGFORMAT_U8;
		}
		else
		{
			psHwSource->eFmt = UF_REGFORMAT_C10;
		}
	}
}

static IMG_VOID GenerateDestModC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PARG psDest, IMG_UINT32 uSat, IMG_UINT32 uScale, IMG_UINT32 uMask)
/*****************************************************************************
 FUNCTION	: GenerateDestMod

 PURPOSE	: Create instructions to a destination modifier.

 PARAMETERS	: psState				- Compiler state.
			  psCodeBlock			- Block to insert the instructions in.
			  psDest				- The destination register.
			  dwSat					- Saturation type to apply.
			  dwScale				- Scale to apply.

 RETURNS	: None.
*****************************************************************************/
{
	if (uScale != UFREG_DMOD_SCALEMUL1)
	{
		if (uScale <= UFREG_DMOD_SCALEMUL8)
		{
			IMG_UINT32	uMul;

			/* Scale up by powers of two by adding the register to itself. */
			for (uMul = 0; uMul < uScale; uMul++)
			{
				PINST	psSopWm;

				/* dest = (1 x dest) + (1 * dest) */
				psSopWm = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psSopWm, ISOPWM);
				psSopWm->asDest[0] = *psDest;
				psSopWm->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
				psSopWm->asArg[0] = *psDest;
				psSopWm->asArg[1] = *psDest;
				psSopWm->u.psSopWm->uCop = psSopWm->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
				psSopWm->u.psSopWm->uSel1 = psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psSopWm->u.psSopWm->bComplementSel1 = psSopWm->u.psSopWm->bComplementSel2 = IMG_TRUE;
				AppendInst(psState, psCodeBlock, psSopWm);
			}
		}
		else
		{
			IMG_UINT32	uDiv;

			/* Scale down by powers of two by multiplying the register by 0.5 */
			for (uDiv = uScale; uDiv <= UFREG_DMOD_SCALEDIV2; uDiv++)
			{
				PINST	psSopWm;

				/* dest = (0.5 * dest) + (0 * 0.5) */
				psSopWm = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psSopWm, ISOPWM);
				psSopWm->asDest[0] = *psDest;
				psSopWm->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
				psSopWm->asArg[0] = *psDest;
				psSopWm->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psSopWm->asArg[1].uNumber = 0x7F;	/* 0.5 in C10 format */
				psSopWm->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
				psSopWm->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
				psSopWm->u.psSopWm->uSel1 = USEASM_INTSRCSEL_SRC2;
				psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psSopWm->u.psSopWm->bComplementSel1 = IMG_FALSE;
				psSopWm->u.psSopWm->bComplementSel2 = IMG_FALSE;
				AppendInst(psState, psCodeBlock, psSopWm);
			}
		}
	}

	/* Apply a saturation by doing a min and max. */
	if (psDest->eFmt == UF_REGFORMAT_C10)
	{
		switch (uSat)
		{
			case UFREG_DMOD_SATZEROMAX:
			{
				PINST	psSopWm;

				/*
					DEST = MAX(DEST, 0)
				*/
				psSopWm = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psSopWm, ISOPWM);
				psSopWm->asDest[0] = *psDest;
				psSopWm->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
				psSopWm->asArg[0] = *psDest;
				psSopWm->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psSopWm->asArg[1].uNumber = 0;
				psSopWm->asArg[1].eFmt = UF_REGFORMAT_U8;
				psSopWm->u.psSopWm->uCop = psSopWm->u.psSopWm->uAop = USEASM_INTSRCSEL_MAX;
				psSopWm->u.psSopWm->uSel1 = psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psSopWm->u.psSopWm->bComplementSel1 = psSopWm->u.psSopWm->bComplementSel2 = IMG_TRUE;
				AppendInst(psState, psCodeBlock, psSopWm);
				break;
			}
			case UFREG_DMOD_SATZEROONE:
			{
				PINST	psSopWm;

				/*
					DEST = MAX(DEST, 0)
				*/
				psSopWm = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psSopWm, ISOPWM);
				psSopWm->asDest[0] = *psDest;
				psSopWm->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
				psSopWm->asArg[0] = *psDest;
				psSopWm->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psSopWm->asArg[1].uNumber = 0;
				psSopWm->asArg[1].eFmt = UF_REGFORMAT_U8;
				psSopWm->u.psSopWm->uCop = psSopWm->u.psSopWm->uAop = USEASM_INTSRCSEL_MAX;
				psSopWm->u.psSopWm->uSel1 = psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psSopWm->u.psSopWm->bComplementSel1 = psSopWm->u.psSopWm->bComplementSel2 = IMG_TRUE;
				AppendInst(psState, psCodeBlock, psSopWm);

				/*
					DEST = MIN(DEST, 1)
				*/
				psSopWm = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psSopWm, ISOPWM);
				psSopWm->asDest[0] = *psDest;
				psSopWm->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
				psSopWm->asArg[0] = *psDest;
				psSopWm->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psSopWm->asArg[1].uNumber = USC_U8_VEC4_ONE;
				psSopWm->asArg[1].eFmt = UF_REGFORMAT_U8;
				psSopWm->u.psSopWm->uCop = psSopWm->u.psSopWm->uAop = USEASM_INTSRCSEL_MIN;
				psSopWm->u.psSopWm->uSel1 = psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psSopWm->u.psSopWm->bComplementSel1 = psSopWm->u.psSopWm->bComplementSel2 = IMG_TRUE;
				AppendInst(psState, psCodeBlock, psSopWm);
				break;
			}
			case UFREG_DMOD_SATNEGONEONE:
			{
				PINST		psSopWm;
				IMG_UINT32	uMinusOneTempNum = GetNextRegister(psState);

				/* 
					Get C10(-1) in a temp register.
				*/
				psSopWm = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psSopWm, ISOPWM);
				psSopWm->asDest[0].uType = USEASM_REGTYPE_TEMP;
				psSopWm->asDest[0].uNumber = uMinusOneTempNum;
				psSopWm->asDest[0].eFmt = UF_REGFORMAT_C10;
				psSopWm->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
				psSopWm->asArg[0].uType = USEASM_REGTYPE_IMMEDIATE;
				psSopWm->asArg[0].uNumber = 0;
				psSopWm->asArg[0].eFmt = UF_REGFORMAT_U8;
				psSopWm->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psSopWm->asArg[1].uNumber = USC_U8_VEC4_ONE;
				psSopWm->asArg[1].eFmt = UF_REGFORMAT_U8;
				psSopWm->u.psSopWm->uCop = psSopWm->u.psSopWm->uAop = USEASM_INTSRCSEL_SUB;
				psSopWm->u.psSopWm->uSel1 = psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psSopWm->u.psSopWm->bComplementSel1 = psSopWm->u.psSopWm->bComplementSel2 = IMG_TRUE;
				AppendInst(psState, psCodeBlock, psSopWm);

				/*
					DEST = MAX(DEST, -1)
				*/
				psSopWm = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psSopWm, ISOPWM);
				psSopWm->asDest[0] = *psDest;
				psSopWm->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
				psSopWm->asArg[0] = *psDest;
				psSopWm->asArg[1].uType = USEASM_REGTYPE_TEMP;
				psSopWm->asArg[1].uNumber = uMinusOneTempNum;
				psSopWm->asArg[1].eFmt = UF_REGFORMAT_C10;
				psSopWm->u.psSopWm->uCop = psSopWm->u.psSopWm->uAop = USEASM_INTSRCSEL_MAX;
				psSopWm->u.psSopWm->uSel1 = psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psSopWm->u.psSopWm->bComplementSel1 = psSopWm->u.psSopWm->bComplementSel2 = IMG_TRUE;
				AppendInst(psState, psCodeBlock, psSopWm);

				/*
					DEST = MIN(DEST, 1)
				*/
				psSopWm = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psSopWm, ISOPWM);
				psSopWm->asDest[0] = *psDest;
				psSopWm->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
				psSopWm->asArg[0] = *psDest;
				psSopWm->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psSopWm->asArg[1].uNumber = USC_U8_VEC4_ONE;
				psSopWm->asArg[1].eFmt = UF_REGFORMAT_U8;
				psSopWm->u.psSopWm->uCop = psSopWm->u.psSopWm->uAop = USEASM_INTSRCSEL_MIN;
				psSopWm->u.psSopWm->uSel1 = psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psSopWm->u.psSopWm->bComplementSel1 = psSopWm->u.psSopWm->bComplementSel2 = IMG_TRUE;
				AppendInst(psState, psCodeBlock, psSopWm);
				break;
			}
		}
	}
}

#if defined(OUTPUT_USCHW) || defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
static IMG_VOID ApplyDestModC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psInputInst)
/*****************************************************************************
 FUNCTION	: ApplyDestModC10

 PURPOSE	: Generate instructions to apply the destination modifiers on an
			  input instruction.

 PARAMETERS	: psState				- Compiler state.
			  psCodeBlock			- Block to insert the instructions in.
			  psInputInst			- Input instruction to generate destination
									modifiers for.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32 uSat = (psInputInst->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32 uScale = (psInputInst->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;

	if (uSat != UFREG_DMOD_SATNONE || uScale != UFREG_DMOD_SCALEMUL1)
	{
		ARG	sDest;

		GetDestinationC10(psState, &psInputInst->sDest, &sDest);
		GenerateDestModC10(psState, psCodeBlock, &sDest, uSat, uScale, psInputInst->sDest.u.byMask);
	}
}
#endif /* defined(OUTPUT_USCHW) || defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */

static PINST BaseConvertF32ImmediateToC10(PINTERMEDIATE_STATE	psState,
										  UF_REGFORMAT			eDestFormat,
										  IMG_UINT32			uImmSel)
/*****************************************************************************
 FUNCTION	: BaseConvertF32ImmediateToC10

 PURPOSE	: Create an instruction to load an F32 immediate value converted 
			  to C10 or U8 into a single channel of a register.

 PARAMETERS	: psState				- Compiler state.
			  eDestFormat			- Format to convert to.
			  uImmSel				- Value to convert. Either UFREG_SWIZ_0,
									UFREG_SWIZ_1, UFREG_SWIZ_2 or UFREG_SWIZ_HALF.

 RETURNS	: A pointer to the created instruction.
*****************************************************************************/
{
	PINST		psPackInst;

	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if ((psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_VEC34) != 0)
	{
		IMG_UINT32	uImmValue;

		psPackInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psPackInst, (eDestFormat == UF_REGFORMAT_C10) ? IVPCKC10FLT : IVPCKU8FLT);

		psPackInst->u.psVec->bPackScale = IMG_TRUE;

		switch (uImmSel)
		{
			case UFREG_SWIZ_0:		uImmValue = FLOAT32_ZERO; break;
			case UFREG_SWIZ_1:		uImmValue = FLOAT32_ONE; break;
			case UFREG_SWIZ_2:		uImmValue = FLOAT32_TWO; break;
			case UFREG_SWIZ_HALF:	uImmValue = FLOAT32_HALF; break;
			default: imgabort();
		}

		SetupImmediateSourceU(psPackInst, 0 /* uArgIdx */, uImmValue, UF_REGFORMAT_F32);
	}
	else
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	{
		psPackInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psPackInst, (eDestFormat == UF_REGFORMAT_C10) ? IPCKC10F32 : IPCKU8F32);

		psPackInst->u.psPck->bScale = IMG_TRUE;

		psPackInst->asArg[0].uType = USEASM_REGTYPE_FPCONSTANT;
		switch (uImmSel)
		{
			case UFREG_SWIZ_0: psPackInst->asArg[0].uNumber = EURASIA_USE_SPECIAL_CONSTANT_ZERO; break;
			case UFREG_SWIZ_1: psPackInst->asArg[0].uNumber = EURASIA_USE_SPECIAL_CONSTANT_FLOAT1; break;
			case UFREG_SWIZ_2: psPackInst->asArg[0].uNumber = EURASIA_USE_SPECIAL_CONSTANT_FLOAT2; break;
			case UFREG_SWIZ_HALF: psPackInst->asArg[0].uNumber = EURASIA_USE_SPECIAL_CONSTANT_FLOAT1OVER2; break;
			default: imgabort();
		}

		psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
		psPackInst->asArg[1].uNumber = 0;
	}

	return psPackInst;
}

static IMG_VOID ConvertF32ImmediateToC10(PINTERMEDIATE_STATE	psState,
										 PCODEBLOCK				psCodeBlock,
										 IMG_UINT32				uDestNum,
										 IMG_UINT32				uDestChan,
										 UF_REGFORMAT			eDestFormat,
										 IMG_UINT32				uImmSel)
/*****************************************************************************
 FUNCTION	: ConvertF32ImmediateToC10

 PURPOSE	: Load an F32 immediate value converted to C10 or U8 into a single
			  channel of a register.

 PARAMETERS	: psState				- Compiler state.
			  psCodeBlock			- Block to insert the instructions in.
			  uDestNum				- C10 or U8 register to set.
			  uDestChan				- Channel to set within the register.
			  eDestFormat			- Format of the register.
			  uImmSel				- Value to convert. Either UFREG_SWIZ_0,
									UFREG_SWIZ_1, UFREG_SWIZ_2 or UFREG_SWIZ_HALF.

 RETURNS	: None.
*****************************************************************************/
{
	PINST	psPackInst;

	psPackInst = BaseConvertF32ImmediateToC10(psState, eDestFormat, uImmSel);

	psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psPackInst->asDest[0].uNumber = uDestNum;
	psPackInst->asDest[0].eFmt = eDestFormat;
	psPackInst->auDestMask[0] = 1 << ConvertInputChannelToIntermediate(psState, uDestChan);

	AppendInst(psState, psCodeBlock, psPackInst);
}


static IMG_VOID SwizzleC10(PINTERMEDIATE_STATE	psState,
						   PCODEBLOCK			psCodeBlock,
						   PARG					psSrc,
						   IMG_UINT32			uSwiz,
						   IMG_UINT32			uMask,
						   IMG_UINT32			uDest,
						   UF_REGFORMAT			eFormat)
/*****************************************************************************
 FUNCTION	: SwizzleC10

 PURPOSE	: Create instructions apply a swizzle to a U8/C10 format value.

 PARAMETERS	: psState				- Compiler state.
			  psCodeBlock			- Block to insert the instructions in.
			  psSrc					- Source register.
			  uSwiz					- Swizzle
			  uMask					- Mask of channels to be swizzled
			  uDest					- Temporary destination for the swizzled
									register.
			  eFormat				- Format of the value to be swizzled.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32	uChan;

	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		IMG_UINT32	uSwizzledChan = (uSwiz >> (uChan * 3)) & 0x7;

		if ((uMask & (1U << uChan)) == 0)
		{
			continue;
		}
		if (uSwizzledChan <= UFREG_SWIZ_W)
		{
			PINST		psPackInst;
			IMG_UINT32	uSrcComponent;

			psPackInst = AllocateInst(psState, IMG_NULL);

			SetOpcode(psState, psPackInst,	
					  (eFormat == UF_REGFORMAT_C10) ? IPCKC10C10 : IPCKU8U8);
			psPackInst->asArg[0] = *psSrc;
			uSrcComponent = ConvertInputChannelToIntermediate(psState, uSwizzledChan);
			SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, uSrcComponent);

			psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psPackInst->asArg[1].uNumber = 0;

			psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psPackInst->asDest[0].uNumber = uDest;
			psPackInst->asDest[0].eFmt = eFormat;
			psPackInst->auDestMask[0] = 1U << ConvertInputChannelToIntermediate(psState, uChan);

			AppendInst(psState, psCodeBlock, psPackInst);
		}
		else
		{
			ConvertF32ImmediateToC10(psState, psCodeBlock, uDest, uChan, eFormat, uSwizzledChan);
		}
	}
}

static IMG_VOID ApplySourceModC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PARG psHwSource, IMG_UINT32 uSMod)
/*****************************************************************************
 FUNCTION	: ApplySourceModC10

 PURPOSE	: Generate code to apply a source modifier.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Code block where the instructions to apply the source modifier should be added.
			  psHwSource		- USE register to which the source modifier should be applied.
			  uSMod				- Source modifier type.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32	uTemp = GetNextRegister(psState);

	switch (uSMod)
	{
		case UFREG_SMOD_COMPLEMENT:
		{
			PINST psInst;

			psInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psInst, ISOP2);
			psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psInst->asDest[0].uNumber = uTemp;
			psInst->asDest[0].eFmt = psHwSource->eFmt;
			psInst->asArg[0] = *psHwSource;
			psInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psInst->asArg[1].uNumber = 0;
			psInst->asArg[1].eFmt = UF_REGFORMAT_U8;
			psInst->u.psSop2->uCOp = psInst->u.psSop2->uAOp = USEASM_INTSRCSEL_ADD;
			psInst->u.psSop2->uCSel1 = psInst->u.psSop2->uASel1 = USEASM_INTSRCSEL_ZERO;
			psInst->u.psSop2->uCSel2 = psInst->u.psSop2->uASel2 = USEASM_INTSRCSEL_ZERO;
			psInst->u.psSop2->bComplementCSel1 = psInst->u.psSop2->bComplementASel1 = IMG_TRUE;
			psInst->u.psSop2->bComplementCSel2 = psInst->u.psSop2->bComplementASel2 = IMG_FALSE;
			psInst->u.psSop2->bComplementCSrc1 = psInst->u.psSop2->bComplementASrc1 = IMG_TRUE;
			AppendInst(psState, psCodeBlock, psInst);
			break;
		}
		case UFREG_SMOD_SIGNED:
		{
			PINST	psInst;

			psInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psInst, ISOPWM);
			psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psInst->asDest[0].uNumber = uTemp;
			psInst->asDest[0].eFmt = psHwSource->eFmt;
			psInst->asArg[0] = *psHwSource;
			psInst->asArg[1] = *psHwSource;
			psInst->u.psSopWm->uCop = psInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
			psInst->u.psSopWm->uSel1 = psInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			psInst->u.psSopWm->bComplementSel1 = psInst->u.psSopWm->bComplementSel2 = IMG_TRUE;
			AppendInst(psState, psCodeBlock, psInst);

			psInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psInst, ISOPWM);
			psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psInst->asDest[0].uNumber = uTemp;
			psInst->asDest[0].eFmt = psHwSource->eFmt;
			psInst->asArg[0] = psInst->asDest[0];
			psInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psInst->asArg[1].uNumber = USC_U8_VEC4_ONE;
			psInst->asArg[1].eFmt = UF_REGFORMAT_U8;
			psInst->u.psSopWm->uCop = psInst->u.psSopWm->uAop = USEASM_INTSRCSEL_SUB;
			psInst->u.psSopWm->uSel1 = psInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			psInst->u.psSopWm->bComplementSel1 = psInst->u.psSopWm->bComplementSel2 = IMG_TRUE;
			AppendInst(psState, psCodeBlock, psInst);
			break;
		}
		case UFREG_SMOD_BIAS:
		{
			PINST	psInst;

			psInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psInst, ISOPWM);
			psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psInst->asDest[0].uNumber = uTemp;
			psInst->asDest[0].eFmt = psHwSource->eFmt;
			psInst->asArg[0] = *psHwSource;
			psInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psInst->asArg[1].uNumber = 0x7f;	/* 0.5 in C10 format */
			psInst->asArg[1].eFmt = UF_REGFORMAT_U8;
			psInst->u.psSopWm->uCop = psInst->u.psSopWm->uAop = USEASM_INTSRCSEL_SUB;
			psInst->u.psSopWm->uSel1 = psInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			psInst->u.psSopWm->bComplementSel1 = psInst->u.psSopWm->bComplementSel2 = IMG_TRUE;
			AppendInst(psState, psCodeBlock, psInst);
			break;
		}
		case UFREG_SMOD_TIMES2:
		{
			PINST	psInst;

			psInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psInst, ISOPWM);
			psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psInst->asDest[0].uNumber = uTemp;
			psInst->asDest[0].eFmt = psHwSource->eFmt;
			psInst->asArg[0] = *psHwSource;
			psInst->asArg[1] = *psHwSource;
			psInst->u.psSopWm->uCop = psInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
			psInst->u.psSopWm->uSel1 = psInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			psInst->u.psSopWm->bComplementSel1 = psInst->u.psSopWm->bComplementSel2 = IMG_TRUE;
			AppendInst(psState, psCodeBlock, psInst);	
			break;
		}
	}

	if (uSMod != UFREG_SMOD_NONE)
	{
		psHwSource->uType = USEASM_REGTYPE_TEMP;
		psHwSource->uNumber = uTemp;
		psHwSource->uIndexType = USC_REGTYPE_NOINDEX;
		psHwSource->uIndexNumber = USC_UNDEF;
		psHwSource->uIndexArrayOffset = USC_UNDEF;
		psHwSource->eFmt = psHwSource->eFmt;
	}
}

static IMG_VOID GetIteratedValueC10(PINTERMEDIATE_STATE psState,
									PCODEBLOCK psCodeBlock,
									UNIFLEX_ITERATION_TYPE eIterationType,
									IMG_UINT32 uCoordinate,
									UF_REGFORMAT eFormat,
									PARG psHwSource,
									IMG_UINT32 uMask,
									IMG_BOOL bProjected)
/*****************************************************************************
 FUNCTION	: GetIteratedValueC10

 PURPOSE	: Load an iterated value in U8 or C10 format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Code block where any extras instructions needed should be added.
			  eIterationType	- Type of the iteration to add.
			  uCoordinate		- Index of the texture coordinate or colour to iteration.
			  eFormat			- Format for the iterated value.
			  uSrc				- Source number.
			  psHwSource		- Output where the hardware format source is
								stored.
			  uMask				- Mask of the channels required in the source.
			  bProjected		- TRUE if the iterated value should be
								projected.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32				uIterTempNum;
	IMG_UINT32				uNumAttributes = 0;
	UNIFLEX_TEXLOAD_FORMAT	eIterFormat = UNIFLEX_TEXLOAD_FORMAT_UNDEF;

	/*
		Convert the input register format to an iteration format.
	*/
	switch (eFormat)
	{
		case UF_REGFORMAT_C10: eIterFormat = UNIFLEX_TEXLOAD_FORMAT_C10; uNumAttributes = 1; break;
		case UF_REGFORMAT_U8: eIterFormat = UNIFLEX_TEXLOAD_FORMAT_U8; uNumAttributes = 1; break;
		default: imgabort();
	}

	/*
		Get a temporary register containing the iterated data.
	*/
	uIterTempNum = GetIteratedValue(psState, eIterationType, uCoordinate, eIterFormat, uNumAttributes);

	/*	
		Set up the intermediate source containing the iterated data.
	*/
	psHwSource->uType = USEASM_REGTYPE_TEMP;
	psHwSource->uNumber = uIterTempNum;
	psHwSource->eFmt = eFormat;
	psHwSource->uIndexType = USC_REGTYPE_NOINDEX;
	psHwSource->uIndexNumber = USC_UNDEF;
	psHwSource->uIndexArrayOffset = USC_UNDEF;

	if (bProjected)
	{
		PINST		psRecipInst;
		PINST		psProjInst;
		PINST		psPackInst;
		IMG_UINT32	uOneOverW = GetNextRegister(psState);
		IMG_UINT32	uProjectedCoord = GetNextRegister(psState);
		IMG_UINT32	uRGBMask = uMask & ((1U << UFREG_DMASK_R_SHIFT) | (1U << UFREG_DMASK_G_SHIFT) | (1U << UFREG_DMASK_B_SHIFT));

		/* Calculate 1/W */
		psRecipInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psRecipInst, IFRCP);
		psRecipInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psRecipInst->asDest[0].uNumber = uOneOverW;
		psRecipInst->asDest[0].eFmt = eFormat;
		SetBit(psRecipInst->auFlag, INST_TYPE_PRESERVE, 1);
		psRecipInst->asArg[0] = *psHwSource;
		SetComponentSelect(psState, psRecipInst, 0 /* uArgIdx */, 3 /* uComponent */);
		AppendInst(psState, psCodeBlock, psRecipInst);

		/* Replicate 1/W to all channels. */
		psPackInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psPackInst, IPCKC10C10);
		psPackInst->asDest[0] = psRecipInst->asDest[0];
		psPackInst->asArg[0] = psRecipInst->asDest[0];
		SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, USC_W_CHAN);
		psPackInst->asArg[1] = psRecipInst->asDest[0];
		SetPCKComponent(psState, psPackInst, 1 /* uArgIdx */, USC_W_CHAN);
		AppendInst(psState, psCodeBlock, psPackInst);

		/* Copy the W channel into the destination. */
		if ((uMask & (1U << UFREG_DMASK_W_SHIFT)) != 0)
		{
			PINST	psMOVInst;

			psMOVInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psMOVInst, IMOV);
			psMOVInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psMOVInst->asDest[0].uNumber = uProjectedCoord;
			psMOVInst->asDest[0].eFmt = eFormat;
			psMOVInst->asArg[0] = *psHwSource;
			AppendInst(psState, psCodeBlock, psMOVInst);
		}

		/* Multiply all the other channels by 1/W */
		psProjInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psProjInst, ISOPWM);
		psProjInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uRGBMask);
		psProjInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psProjInst->asDest[0].uNumber = uProjectedCoord;
		psProjInst->asDest[0].eFmt = eFormat;
		psProjInst->asArg[0] = *psHwSource;
		psProjInst->asArg[1] = psRecipInst->asDest[0];
		psProjInst->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
		psProjInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
		psProjInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
		psProjInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_SRC1;
		psProjInst->u.psSopWm->bComplementSel1 = IMG_FALSE;
		psProjInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
		AppendInst(psState, psCodeBlock, psProjInst);

		*psHwSource = psProjInst->asDest[0];
	}
}

static IMG_VOID LoadAlwaysFloatSourceC10(PINTERMEDIATE_STATE psState,
										 PCODEBLOCK psCodeBlock,
										 PUF_REGISTER psSource,
										 PARG psHwSource,
										 IMG_UINT32 uMask,
										 IMG_UINT32 uSwiz)
/*****************************************************************************
 FUNCTION	: LoadAlwaysFloatSourceC10

 PURPOSE	: Get a source register type which is always floating point format 
			  in a C10 format register.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Code block where any extras instructions needed should be added.
			  psSource			- Input format source.
			  psHwSource		- Output where the hardware format source is
								stored.
			  uMask				- Mask of channels required.
			  uSwiz				- Swizzle to apply.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32	uChan;
	PINST		psPackInst;
	IMG_UINT32	uResultTempNum;

	/*
		Get a register to use for the vertex input in C10/U8 format.
	*/
	uResultTempNum = GetNextRegister(psState);

	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if (psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_VEC34)
	{
		IMG_UINT32	uUsedChanMask = SwizzleMask(uSwiz, uMask);
		UF_REGISTER	sSourceNoMod;

		sSourceNoMod = *psSource;
		sSourceNoMod.byMod = 0;
		sSourceNoMod.eFormat = UF_REGFORMAT_F32;

		psPackInst = AllocateInst(psState, NULL);
		SetOpcode(psState, psPackInst, (psSource->eFormat == UF_REGFORMAT_C10) ? IVPCKC10FLT : IVPCKU8FLT);

		psPackInst->u.psVec->bPackScale = IMG_TRUE;

		psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psPackInst->asDest[0].uNumber = uResultTempNum;
		psPackInst->asDest[0].eFmt = psSource->eFormat;

		psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);

		GetSourceF32_Vec(psState, 
						 psCodeBlock, 
						 &sSourceNoMod, 
						 uUsedChanMask,
						 psPackInst,
						 0 /* uSrcIdx */);

		psPackInst->u.psVec->auSwizzle[0] = ConvertSwizzle(psState, uSwiz);

		AppendInst(psState, psCodeBlock, psPackInst);
	}
	else
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	{
		UF_REGISTER	sF32Source;

		sF32Source = *psSource;
		sF32Source.eFormat = UF_REGFORMAT_F32;
		sF32Source.u.uSwiz = (IMG_UINT16)uSwiz;

		for	(uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
		{
			if ((uMask & (1U << uChan)) == 0)
			{
				continue;
			}
	
			/*
				Pack from the vertex shader input in F32 format to either C10 or U8.
			*/
			psPackInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psPackInst,
				  (psSource->eFormat == UF_REGFORMAT_C10) ? IPCKC10F32 : IPCKU8F32);
			psPackInst->u.psPck->bScale = IMG_TRUE;
			psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psPackInst->asDest[0].uNumber = uResultTempNum;
			psPackInst->asDest[0].eFmt = psSource->eFormat;
			psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1U << uChan);
			GetSourceF32(psState, 
						 psCodeBlock,
						 &sF32Source, 
						 uChan, 
						 &psPackInst->asArg[0],
						 IMG_FALSE,
						 NULL);
			psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psPackInst->asArg[1].uNumber = 0;
			AppendInst(psState, psCodeBlock, psPackInst);
		}
	}
	
	/*
		Form an intermediate source referencing the result register.
	*/
	psHwSource->uType = USEASM_REGTYPE_TEMP;
	psHwSource->uNumber = uResultTempNum;
	psHwSource->uIndexType = USC_REGTYPE_NOINDEX;
	psHwSource->uIndexNumber = USC_UNDEF;
	psHwSource->uIndexArrayOffset = USC_UNDEF;
	psHwSource->eFmt = psSource->eFormat;
}

static IMG_VOID LoadHwConstC10(PINTERMEDIATE_STATE psState, 
							   PCODEBLOCK psCodeBlock, 
							   IMG_UINT32 uNum,
							   PARG psHwSource, 
							   IMG_UINT32 uMask,
							   IMG_BOOL bMultiFormat)
/*****************************************************************************
 FUNCTION	: LoadHwConstC10
    
 PURPOSE	: Get one of the hardware constants in a C10 format register.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Code block where any extras instructions needed should be added.
			  uNum				- Hardware constant number.
			  psHwSource		- Output where the hardware format source is
								stored.
			  uMask				- Mask of channels required.
			  
 RETURNS	: None.
*****************************************************************************/
{
	psHwSource->uIndexType = USC_REGTYPE_NOINDEX;
	psHwSource->uIndexNumber = USC_UNDEF;
	psHwSource->uIndexArrayOffset = USC_UNDEF;
	switch (uNum)
	{
		case HW_CONST_0:	
		{
			psHwSource->uType = USEASM_REGTYPE_IMMEDIATE;
			psHwSource->uNumber = 0;
			psHwSource->eFmt = UF_REGFORMAT_U8;
			break;
		}
		case HW_CONST_1:
		{
			if (bMultiFormat)
			{
				psHwSource->uType = USEASM_REGTYPE_IMMEDIATE;
				psHwSource->uNumber = USC_U8_VEC4_ONE;
				psHwSource->eFmt = UF_REGFORMAT_U8;
			}
			else
			{
				IMG_UINT32	uChan;
				IMG_UINT32	uTemp = GetNextRegister(psState);

				for	(uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
				{			
					if ((uMask & (1U << uChan)) == 0)
					{
						continue;
					}

					ConvertF32ImmediateToC10(psState, psCodeBlock, uTemp, uChan, UF_REGFORMAT_C10, UFREG_SWIZ_1);
				}
		
				InitInstArg(psHwSource);
				psHwSource->uType = USEASM_REGTYPE_TEMP;
				psHwSource->uNumber = uTemp;
				psHwSource->eFmt = UF_REGFORMAT_C10;
			}
			break;
		}
		case HW_CONST_HALF:
		{
			if (bMultiFormat)
			{
				psHwSource->uType = USEASM_REGTYPE_IMMEDIATE;
				psHwSource->uNumber = 0x80808080;
				psHwSource->eFmt = UF_REGFORMAT_U8;
			}
			else
			{
				IMG_UINT32	uChan;
				IMG_UINT32	uTemp = GetNextRegister(psState);

				for	(uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
				{			
					if ((uMask & (1U << uChan)) == 0)
					{
						continue;
					}
		
					ConvertF32ImmediateToC10(psState, psCodeBlock, uTemp, uChan, UF_REGFORMAT_C10, UFREG_SWIZ_HALF);
				}
		
				InitInstArg(psHwSource);
				psHwSource->uType = USEASM_REGTYPE_TEMP;
				psHwSource->uNumber = uTemp;
				psHwSource->eFmt = UF_REGFORMAT_C10;
			}
			break;
		}
		case HW_CONST_2:
		{
			IMG_UINT32	uChan;
			IMG_UINT32	uTemp = GetNextRegister(psState);

			for	(uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
			{			
				if ((uMask & (1U << uChan)) == 0)
				{
					continue;
				}
		
				ConvertF32ImmediateToC10(psState, psCodeBlock, uTemp, uChan, UF_REGFORMAT_C10, UFREG_SWIZ_2);
			}
		
			InitInstArg(psHwSource);
			psHwSource->uType = USEASM_REGTYPE_TEMP;
			psHwSource->uNumber = uTemp;
			psHwSource->eFmt = UF_REGFORMAT_C10;
			break;
		}
		default:
		{
			imgabort();
			break;
		}
	}
}

static IMG_VOID LoadHwConstU8(PINTERMEDIATE_STATE psState,
							  IMG_UINT32 uNum,
							  PARG psHwSource)
/*****************************************************************************
 FUNCTION	: LoadHwConstU8
    
 PURPOSE	: Get one of the hardware constants in a U8 format register.

 PARAMETERS	: psState		- Internal compiler state
			  uNum			- Hardware constant number.
			  psHwSource	- Output where the hardware format source is
								stored.
			  
 RETURNS	: None.
*****************************************************************************/
{
	psHwSource->uIndexType = USC_REGTYPE_NOINDEX;
	psHwSource->uIndexNumber = USC_UNDEF;
	psHwSource->uIndexArrayOffset = USC_UNDEF;
	psHwSource->eFmt = UF_REGFORMAT_U8;

	switch (uNum)
	{
		case HW_CONST_0:	
		{
			psHwSource->uType = USEASM_REGTYPE_IMMEDIATE;
			psHwSource->uNumber = 0;
			break;
		}
		case HW_CONST_1:
		case HW_CONST_2:
		{
			psHwSource->uType = USEASM_REGTYPE_IMMEDIATE;
			psHwSource->uNumber = USC_U8_VEC4_ONE;
			break;
		}
		case HW_CONST_HALF:
		{
			psHwSource->uType = USEASM_REGTYPE_IMMEDIATE;
			psHwSource->uNumber = 0x80808080;
			break;
		}
		default:
		{
			imgabort();
			break;
		}
	}
}

static IMG_VOID LoadBackfaceC10(PINTERMEDIATE_STATE psState, 
								PCODEBLOCK psCodeBlock,
								PARG psHwSource)
/*****************************************************************************
 FUNCTION	: LoadBackfaceC10
    
 PURPOSE	: Get the setting of the backface bit in a C10 format register.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Code block where any extras instructions needed should be added.
			  psHwSource		- Output where the hardware format source is
								stored.
			  
 RETURNS	: None.
*****************************************************************************/
{
	PINST		psSopInst;
	IMG_UINT32	uTemp = GetNextRegister(psState);

	/*
		Test the setting of the backface bit.
	*/
	CheckFaceType(psState, psCodeBlock, USC_PREDREG_TEMP, IMG_FALSE /* bFrontFace */); 

	/*
		If the backface bit is FALSE then put 1 into a register.
	*/
	psSopInst = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psSopInst, ISOPWM);
	psSopInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psSopInst->asDest[0].uNumber = uTemp;
	psSopInst->asDest[0].eFmt = UF_REGFORMAT_C10;
	psSopInst->asArg[0].uType = USEASM_REGTYPE_IMMEDIATE;
	psSopInst->asArg[0].uNumber = USC_U8_VEC4_ONE;
	psSopInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
	psSopInst->asArg[1].uNumber = 0;
	psSopInst->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
	psSopInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
	psSopInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
	psSopInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
	psSopInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
	psSopInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
	AppendInst(psState, psCodeBlock, psSopInst);

	/*
		If the backface bit is TRUE then put -1 into a register.
	*/
	psSopInst = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psSopInst, ISOPWM);
	SetPredicate(psState, psSopInst, USC_PREDREG_TEMP, IMG_FALSE /* bPredNegate */);
	psSopInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psSopInst->asDest[0].uNumber = uTemp;
	psSopInst->asDest[0].eFmt = UF_REGFORMAT_C10;
	psSopInst->asArg[0].uType = USEASM_REGTYPE_IMMEDIATE;
	psSopInst->asArg[0].uNumber = 0;
	psSopInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
	psSopInst->asArg[1].uNumber = USC_U8_VEC4_ONE;
	psSopInst->u.psSopWm->uCop = USEASM_INTSRCSEL_SUB;
	psSopInst->u.psSopWm->uAop = USEASM_INTSRCSEL_SUB;
	psSopInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
	psSopInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
	psSopInst->u.psSopWm->bComplementSel1 = IMG_FALSE;
	psSopInst->u.psSopWm->bComplementSel2 = IMG_TRUE;
	AppendInst(psState, psCodeBlock, psSopInst);

	psHwSource->uType = USEASM_REGTYPE_TEMP;
	psHwSource->uNumber = uTemp;
	psHwSource->eFmt = UF_REGFORMAT_C10;
	psHwSource->uIndexType = USC_REGTYPE_NOINDEX;
	psHwSource->uIndexNumber = USC_UNDEF;
	psHwSource->uIndexArrayOffset = USC_UNDEF;
}

/*****************************************************************************
 FUNCTION	: GetC10OrU8StaticConstant
    
 PURPOSE	: Check for a constant value which is available directly as an c10 or u8 value.

 PARAMETERS	: psState			- Compiler state.
			  psSource			- Source register to check.
			  uSrcChan			- Source channel to check.
			  bMultiFormat		- If set then U8 format constants can be used too.
			  psHwSource		- If the constant value exists then on return
								  psHwSource is set up to use it.
			  
 RETURNS	: TRUE if the constant value is available directly.
*****************************************************************************/
static IMG_BOOL GetC10OrU8StaticConstant(PINTERMEDIATE_STATE	psState, 
										 PUF_REGISTER			psSource,
										 IMG_UINT32				uMask,
										 IMG_UINT32				uSwiz,
										 IMG_BOOL				bMultiFormat,
										 PARG					psHwSource)
{
	if (psSource->eRelativeIndex == UFREG_RELATIVEINDEX_NONE)
	{
		IMG_BOOL bFirst;
		IMG_FLOAT fValue;
		IMG_BOOL bNonStatic;
		IMG_UINT32 uChan;

		/*
			Check that all the channels used from the constant are static and
			that they all have the same value.
		*/
		bFirst = IMG_TRUE;
		bNonStatic = IMG_FALSE;
		fValue = 0.0f;
		for (uChan = 0; uChan < 4; uChan++)
		{
			if (uMask & (1U << uChan))
			{
				IMG_UINT32	uSrcChan = EXTRACT_CHAN(uSwiz, uChan);
				IMG_UINT32	uChanValue;
				IMG_FLOAT	fChanValue;

				if (!CheckForStaticConst(psState, psSource->uNum, uSrcChan, psSource->uArrayTag, &uChanValue))
				{
					return IMG_FALSE;
				}
				fChanValue = *(IMG_PFLOAT)&uChanValue;
				if (!bFirst && fValue != fChanValue)
				{
					return IMG_FALSE;
				}

				bFirst = IMG_FALSE;
				fValue = fChanValue;
			}
		}
		
		/*
			Check if there is a equivalent hardware constant.
		*/
		if (!bNonStatic)
		{
			if (fValue == 0.0f)
			{
				psHwSource->uType = USEASM_REGTYPE_IMMEDIATE;
				psHwSource->uNumber = 0;
				psHwSource->uIndexType = USC_REGTYPE_NOINDEX;
				psHwSource->uIndexNumber = USC_UNDEF;
				psHwSource->uIndexArrayOffset = USC_UNDEF;
				psHwSource->eFmt = UF_REGFORMAT_U8;
				return IMG_TRUE;
			}
			else if (fValue == 1.0f)
			{	
				if	(bMultiFormat || psSource->eFormat == UF_REGFORMAT_U8 || psSource->eFormat == UF_REGFORMAT_F32)
				{
					psHwSource->uType = USEASM_REGTYPE_IMMEDIATE;
					psHwSource->uNumber = USC_U8_VEC4_ONE;
					psHwSource->uIndexType = USC_REGTYPE_NOINDEX;
					psHwSource->uIndexNumber = USC_UNDEF;
					psHwSource->uIndexArrayOffset = USC_UNDEF;
					psHwSource->eFmt = UF_REGFORMAT_U8;
					return IMG_TRUE;
				}
			}
		}	
	}
	return IMG_FALSE;
}

IMG_INTERNAL
IMG_BOOL CanOverrideSwiz(PUF_REGISTER psSrc)
/*****************************************************************************
 FUNCTION	: CanOverrideSwiz
    
 PURPOSE	: Check if its possible to do a swizzle on a source directly in
			  the instruction which uses the source.

 PARAMETERS	: psSrc		- Source to check.
			  
 RETURNS	: TRUE or FALSE.
*****************************************************************************/
{
	if (
			psSrc->eType == UFREG_TYPE_CONST &&
			psSrc->eRelativeIndex != UFREG_RELATIVEINDEX_NONE &&
			psSrc->u1.uRelativeStrideInBytes < LONG_SIZE
	   )
	{
		return IMG_FALSE;
	}
	return IMG_TRUE;
}

static IMG_VOID ExpandAlignedConstantAccess(PINTERMEDIATE_STATE		psState,
											PCODEBLOCK				psCodeBlock,
											PUF_REGISTER			psSource,
											PARG					psHwSource)
/*****************************************************************************
 FUNCTION	: ExpandAlignedConstantAccess
    
 PURPOSE	: Generate instructions do an aligned access to C10 constants.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to insert the instructions into.
			  psSource			- Input source.
			  psHwSource		- Returns the register to access to access the
								constant data in intermediate instruction.
			  
 RETURNS	: Nothing.
*****************************************************************************/
{
	LoadConstant(psState, 
				 psCodeBlock, 
				 psSource, 
				 0, 
				 psHwSource, 
				 NULL /* puComponent */,
				 IMG_FALSE, 
				 NULL, 
				 UF_REGFORMAT_C10, 
				 IMG_FALSE /* bC10Subcomponent */,
				 0);
}

static IMG_VOID ExpandUnalignedConstantAccess(PINTERMEDIATE_STATE		psState,
											  PCODEBLOCK				psCodeBlock,
											  IMG_UINT32				uMask,
											  IMG_UINT32				uInputSwiz,
											  PUF_REGISTER				psSource,
											  PARG						psHwSource,
											  IMG_PUINT32				puSwiz)
/*****************************************************************************
 FUNCTION	: ExpandUnalignedConstantAccess
    
 PURPOSE	: Generate instructions to load a constant with an unaligned dynamic
			  index component by component.

 PARAMETERS	: 

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32	uChan;
	IMG_UINT32	uAddressRegisterIndex;
	IMG_UINT32	uResultTempNum;

	ASSERT(psSource->eRelativeIndex >= UFREG_RELATIVEINDEX_A0X && psSource->eRelativeIndex <= UFREG_RELATIVEINDEX_A0W);
	uAddressRegisterIndex = psSource->eRelativeIndex - UFREG_RELATIVEINDEX_A0X;

	/*
		Register to use for the loaded constant vector.
	*/
	uResultTempNum = GetNextRegister(psState);

	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		ARG			sArg;
		IMG_UINT32	uSrcChan = EXTRACT_CHAN(uInputSwiz, uChan);
		IMG_UINT32	uNextChan;
		IMG_UINT32	uAddressRegisterNum;
		IMG_UINT32	uCompOffset;

		if ((uMask & (1U << uChan)) == 0)
		{
			continue;
		}

		uCompOffset = uSrcChan;
		uAddressRegisterNum = (uAddressRegisterIndex * 4) + uCompOffset;
		
		/*
			Insert instructions to load the 10-bit channel into the low 10-bits of an
			intermediate register.
		*/
		LoadConstant(psState, 
					 psCodeBlock, 
					 psSource, 
					 0 /* uSrcChan */, 
					 &sArg, 
					 NULL /* puComponent */,
					 IMG_FALSE /* bAllowSourceMod */, 
					 NULL /* pbNegate */, 
					 UF_REGFORMAT_C10, 
					 IMG_TRUE /* bC10Subcomponent */,
					 uCompOffset);

		/*
			For any channels that swizzle in this component use the loaded value.
		*/
		for (uNextChan = uChan; uNextChan < CHANNELS_PER_INPUT_REGISTER; uNextChan++)
		{
			PINST		psPackInst;

			if (EXTRACT_CHAN(uInputSwiz, uNextChan) != uSrcChan)
			{
				continue;
			}

			psPackInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psPackInst, IPCKC10C10);
			psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uNextChan);
			psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psPackInst->asDest[0].uNumber = uResultTempNum;
			psPackInst->asDest[0].eFmt = UF_REGFORMAT_C10;
			psPackInst->asArg[0] = sArg;
			psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psPackInst->asArg[1].uNumber = 0;
			AppendInst(psState, psCodeBlock, psPackInst);

			uMask &= ~(1U << uNextChan);
		}
	}

	psHwSource->uType = USEASM_REGTYPE_TEMP;
	psHwSource->uNumber = uResultTempNum;
	psHwSource->uIndexType = USC_REGTYPE_NOINDEX;
	psHwSource->uIndexNumber = USC_UNDEF;
	psHwSource->uIndexArrayOffset = USC_UNDEF;
	psHwSource->eFmt = UF_REGFORMAT_C10;

	/*
		No need to apply the swizzle again.
	*/
	*puSwiz = UFREG_SWIZ_NONE;
}

static IMG_VOID ConvertU8ArgToC10(PINTERMEDIATE_STATE psState, 
								  PCODEBLOCK psCodeBlock, 
								  PARG psArgIn, 
								  PARG psArgOut, 
								  IMG_UINT32 uMask)
/*****************************************************************************
 FUNCTION	: ConvertU8ArgToC10

 PURPOSE	: Convert an input argument in U8 format to C10 format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psArgIn		    - Input Argument in U8 format.
			  psArgOut		    - Output Argument in C10 format.
			  uDestMask         - Destination mask for output.

 RETURNS	: None.
*****************************************************************************/
{
	PINST psSopWmInst;
	psSopWmInst = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psSopWmInst, ISOPWM);
	
	psSopWmInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psSopWmInst->asDest[0].uNumber = GetNextRegister(psState);
	psSopWmInst->asDest[0].eFmt = UF_REGFORMAT_C10;
	
	psSopWmInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
	
	psSopWmInst->asArg[0] = *psArgIn;
	*psArgOut = psSopWmInst->asDest[0];

	psSopWmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
	psSopWmInst->asArg[1].uNumber = 0;
	psSopWmInst->u.psSopWm->uCop = psSopWmInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
	psSopWmInst->u.psSopWm->uSel1 = psSopWmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
	psSopWmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
	psSopWmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
	AppendInst(psState, psCodeBlock, psSopWmInst);
}

static IMG_VOID ConvertC10ArgToU8(PINTERMEDIATE_STATE psState, 
								  PCODEBLOCK psCodeBlock, 
								  PARG psArgIn, 
								  PARG psArgOut, 
								  IMG_UINT32 uMask)
/*****************************************************************************
 FUNCTION	: ConvertC10ArgToU8

 PURPOSE	: Convert an input argument in C10 format to U8 format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psArgIn		    - Input Argument in C10 format.
			  psArgOut		    - Output Argument in CU8 format.
			  uDestMask         - Destination mask for output.

 RETURNS	: None.
*****************************************************************************/
{
	PINST psSopWmInst;
	psSopWmInst = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psSopWmInst, ISOPWM);
	
	psSopWmInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psSopWmInst->asDest[0].uNumber = GetNextRegister(psState);
	psSopWmInst->asDest[0].eFmt = UF_REGFORMAT_U8;
	
	psSopWmInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
	
	psSopWmInst->asArg[0] = *psArgIn;
	*psArgOut = psSopWmInst->asDest[0];

	psSopWmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
	psSopWmInst->asArg[1].uNumber = 0;
	psSopWmInst->asArg[1].eFmt = UF_REGFORMAT_C10;

	psSopWmInst->u.psSopWm->uCop = psSopWmInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
	psSopWmInst->u.psSopWm->uSel1 = psSopWmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
	psSopWmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
	psSopWmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
	AppendInst(psState, psCodeBlock, psSopWmInst);
}

IMG_INTERNAL 
IMG_VOID GetSourceC10(PINTERMEDIATE_STATE psState, 
					  PCODEBLOCK psCodeBlock, 
					  PUF_REGISTER psSource, 
					  IMG_BYTE bySrcMod,
					  PARG psHwSource, 
					  IMG_UINT32 uMask,
					  IMG_BOOL bIgnoreSwiz,
					  IMG_BOOL bMultiFormat,
					  UF_REGFORMAT	eRequiredFmt)
/*****************************************************************************
 FUNCTION	: GetSourceC10
    
 PURPOSE	: Get the hardware source corresponding to an input source in c10/u8
			  format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Code block where any extras instructions needed should be added.
			  psSource			- Input source register.
			  bySrcMod			- Input register source modifier.
			  uSrc				- Source to the instruction.
			  psHwSource		- Output where the hardware format source is
								stored.
			  uMask				- Mask of the channels required in the source.
			  eRequiredFmt      - Format in which constant should be loaded.
			  
 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32 uSMod = (bySrcMod & UFREG_SMOD_MASK) >> UFREG_SMOD_SHIFT;
	IMG_UINT32 uSwiz = bIgnoreSwiz ? UFREG_SWIZ_NONE : psSource->u.uSwiz;
	IMG_UINT32 uSwizzledMask = SwizzleMask(uSwiz, uMask);
	IMG_UINT32 uMaskForSwizzle = MaskToSwiz(uMask);

	ASSERT(psSource->eFormat == UF_REGFORMAT_C10 ||
			psSource->eFormat == UF_REGFORMAT_U8 ||
			psSource->eFormat == UF_REGFORMAT_U8_UN ||
			psSource->eFormat == UF_REGFORMAT_I8_UN);

	ASSERT(uMask <= USC_DESTMASK_FULL);

	InitInstArg(psHwSource);

	switch (psSource->eType)
	{
		case UFREG_TYPE_TEMP:
		{
			ASSERT(psSource->eRelativeIndex == UFREG_RELATIVEINDEX_NONE);
			psHwSource->uType = USEASM_REGTYPE_TEMP;
			psHwSource->uNumber = ConvertTempRegisterNumberC10(psState, psSource);
			psHwSource->eFmt = psSource->eFormat;
			break;
		}
		case UFREG_TYPE_PSOUTPUT:
		{
			ConvertPixelShaderResultArg(psState, psSource, psHwSource);
			psHwSource->eFmt = psSource->eFormat;
			break;
		}
		case UFREG_TYPE_COL:
		{
			UF_REGFORMAT	eColFormat;

			/*
				The diffuse and specular colours are stored in U8 format so use that
				precision for the iteration if the instruction accepts both u8
				and c10 format sources.
			*/
			if (bMultiFormat)
			{
				eColFormat = UF_REGFORMAT_U8;
			}
			else
			{

				eColFormat = psSource->eFormat;
			}

			GetIteratedValueC10(psState,
								psCodeBlock,
								UNIFLEX_ITERATION_TYPE_COLOUR,
								psSource->uNum,
								eColFormat,
								psHwSource,
								uSwizzledMask,
								IMG_FALSE);
			break;
		}
		case UFREG_TYPE_TEXCOORD:
		case UFREG_TYPE_TEXCOORDP:
		case UFREG_TYPE_TEXCOORDPIFTC:
		{
			UF_REGFORMAT eFormat = psSource->eFormat;
			IMG_BOOL	bProjected = (psSource->eType == UFREG_TYPE_TEXCOORDP) ? IMG_TRUE : IMG_FALSE;
			if (psSource->eType == UFREG_TYPE_TEXCOORDPIFTC)
			{
				ASSERT(psSource->eRelativeIndex == UFREG_RELATIVEINDEX_NONE);
				if (GetBit(psState->psSAOffsets->auProjectedCoordinateMask, psSource->uNum))
				{
					bProjected = IMG_TRUE;
				}
			}
			if(eFormat == UF_REGFORMAT_U8)
			{
				eFormat = UF_REGFORMAT_C10;
			}
			GetIteratedValueC10(psState,
								psCodeBlock,
								UNIFLEX_ITERATION_TYPE_TEXTURE_COORDINATE,
								psSource->uNum,
								eFormat,
								psHwSource,
								uSwizzledMask,
								bProjected);

			/* Format conversion to U8 is required. */
			if(psSource->eFormat == UF_REGFORMAT_U8)
			{
				ConvertC10ArgToU8(psState, psCodeBlock, psHwSource, psHwSource, USC_DESTMASK_FULL);
			}
			break;
		}
		case UFREG_TYPE_MISC:
		{			
			if (psSource->uNum == UF_MISC_FACETYPE)
			{
				LoadBackfaceC10(psState, psCodeBlock, psHwSource);
			}
			else if (psSource->uNum == UF_MISC_POSITION)
			{
				LoadAlwaysFloatSourceC10(psState, psCodeBlock, psSource, psHwSource, uMask, uSwiz);
				uSwiz = UFREG_SWIZ_NONE;
			}
			else
			{
				UNIFLEX_ITERATION_TYPE	eIterationType;
				
				if (psSource->uNum == UF_MISC_FOG)
				{
					eIterationType = UNIFLEX_ITERATION_TYPE_FOG;
				}
				else
				{
					/* 
						Primitive ID will always be a 32 bit value. 
					*/
					imgabort();
				}

				GetIteratedValueC10(psState,
									psCodeBlock,
									eIterationType,
									0 /* uCoordinate */,
									psSource->eFormat,
									psHwSource,
									uSwizzledMask,
									IMG_FALSE);
			}
			break;
		}
		case UFREG_TYPE_CONST:
		{
			/*
				Check for a constant we can replace by a hardware constant.
			*/
			if (GetC10OrU8StaticConstant(psState, psSource, uMask, uSwiz, bMultiFormat, psHwSource))
			{
				uSwiz = UFREG_SWIZ_NONE;
			}
			else
			{
				if (eRequiredFmt == UF_REGFORMAT_U8)
				{
					LoadConstant(psState, 
								 psCodeBlock, 
								 psSource, 
								 0, 
								 psHwSource, 
								 NULL /* puComponent */,
								 IMG_FALSE, 
								 NULL, 
								 UF_REGFORMAT_U8,
								 IMG_FALSE /* bC10Subcomponent */,
								 0);
				}
				else if (eRequiredFmt == UF_REGFORMAT_F32)
				{
					IMG_UINT32	uChan;
					IMG_UINT32	uPackDest = GetNextRegister(psState);

					/*
						Load the constants as F32 and pack it to U8 format in a temporary register.
					*/
					for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
					{
						PINST		psPackInst;
	
						if ((uSwizzledMask & (1U << uChan)) == 0)
						{
							continue;
						}
						
						psPackInst = AllocateInst(psState, IMG_NULL);
						SetOpcode(psState, psPackInst, IPCKU8F32);
						psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
						psPackInst->u.psPck->bScale = IMG_TRUE;
						psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
						psPackInst->asDest[0].uNumber = uPackDest;
						psPackInst->asDest[0].eFmt = UF_REGFORMAT_U8;
						LoadConstant(psState, 
									 psCodeBlock, 
									 psSource, 
									 uChan, 
									 &psPackInst->asArg[0], 
									 NULL /* puComponent */,
									 IMG_FALSE, 
									 NULL, 
									 UF_REGFORMAT_F32, 
									 IMG_FALSE /* bC10SubcomponentIndex */,
									 0);
						psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
						psPackInst->asArg[1].uNumber = 0;
						AppendInst(psState, psCodeBlock, psPackInst);
					}

					/*
						Return the temporary register containing the packed constants.
					*/
					psHwSource->uType = USEASM_REGTYPE_TEMP;
					psHwSource->uNumber = uPackDest;
					psHwSource->eFmt = UF_REGFORMAT_U8;
				}
				else
				{
					if (
							psSource->eRelativeIndex != UFREG_RELATIVEINDEX_NONE &&
							(psState->uCompilerFlags & UF_CONSTEXPLICTADDRESSMODE) == 0 &&
							psSource->u1.uRelativeStrideInBytes < LONG_SIZE
					   )
					{
						ASSERT(!bIgnoreSwiz);

						ExpandUnalignedConstantAccess(psState,
													  psCodeBlock,
													  uMask,
													  uSwiz,
													  psSource,
													  psHwSource,
													  &uSwiz);
					}
					else
					{
						ExpandAlignedConstantAccess(psState,
													psCodeBlock,
													psSource,
													psHwSource);
					}
				}
			}
			break;
		}
		case UFREG_TYPE_HW_CONST:
		{
			if (psSource->eFormat == UF_REGFORMAT_C10)
			{
				LoadHwConstC10(psState, psCodeBlock, psSource->uNum, psHwSource, uMask, bMultiFormat);
			}
			else
			{
				LoadHwConstU8(psState, psSource->uNum, psHwSource);
			}
			uSwiz = UFREG_SWIZ_NONE;
			break;
		}
		case UFREG_TYPE_VSINPUT:
		{
			LoadAlwaysFloatSourceC10(psState, psCodeBlock, psSource, psHwSource, uMask, uSwiz);
			uSwiz = UFREG_SWIZ_NONE;
			break;
		}
		case UFREG_TYPE_INDEXABLETEMP:
		{
			IMG_UINT32	uTemp = GetNextRegister(psState);

			LoadStoreIndexableTemp(psState, 
								   psCodeBlock, 
								   IMG_TRUE, 
								   UF_REGFORMAT_C10, 
								   psSource, 
								   ConvertInputWriteMaskToIntermediate(psState, uSwizzledMask), 
								   uTemp, 
								   0);
			/* Set the hw register to the packed register */
			psHwSource->uType = USEASM_REGTYPE_TEMP;
			psHwSource->uNumber = uTemp;
			psHwSource->eFmt = UF_REGFORMAT_C10;
			break;
		}
		case UFREG_TYPE_VSOUTPUT:
		{
			LoadAlwaysFloatSourceC10(psState, psCodeBlock, psSource, psHwSource, uMask, uSwiz);
			uSwiz = UFREG_SWIZ_NONE;
			break;
		}
		default:
		{
			imgabort();
			break;
		}
	}

	/*
		Apply any swizzle to the source register with PCKC10C10 instructions.
	*/
	if ((uSwiz & uMaskForSwizzle) != (UFREG_SWIZ_NONE & uMaskForSwizzle))
	{
		IMG_UINT32	uTemp = GetNextRegister(psState);

		SwizzleC10(psState, 
				   psCodeBlock, 
				   psHwSource, 
				   uSwiz, 
				   uMask, 
				   uTemp, 
				   psHwSource->eFmt);

		psHwSource->uType = USEASM_REGTYPE_TEMP;
		psHwSource->uNumber = uTemp;
	}

	/*
		Apply any of the DX source modifiers e.g. bias or complement.
	*/
	ApplySourceModC10(psState, psCodeBlock, psHwSource, uSMod);

	if (bySrcMod & UFREG_SOURCE_ABS)
	{
		PINST	psNegateInst;
		PINST	psMovcInst;

		/*
			SOPWM	rTemp = 0 - rDest
		*/
		psNegateInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psNegateInst, ISOPWM);
		psNegateInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
		psNegateInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psNegateInst->asDest[0].uNumber = GetNextRegister(psState);
		if(psHwSource->eFmt == UF_REGFORMAT_U8)
		{
			psNegateInst->asDest[0].eFmt = UF_REGFORMAT_U8;
		}
		else
		{
			psNegateInst->asDest[0].eFmt = UF_REGFORMAT_C10;
		}
		psNegateInst->asArg[0].uType = USEASM_REGTYPE_IMMEDIATE;
		psNegateInst->asArg[0].uNumber = 0;
		psNegateInst->asArg[0].eFmt = UF_REGFORMAT_U8;
		psNegateInst->asArg[1] = *psHwSource;
		psNegateInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
		psNegateInst->u.psSopWm->bComplementSel1 = IMG_FALSE;
		psNegateInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
		psNegateInst->u.psSopWm->bComplementSel2 = IMG_TRUE;
		psNegateInst->u.psSopWm->uCop = psNegateInst->u.psSopWm->uAop = USEASM_INTSRCSEL_SUB;
		AppendInst(psState, psCodeBlock, psNegateInst);

		/*
			rDest = (rDest >= 0) ? rDest : rTemp
		*/
		if(psHwSource->eFmt == UF_REGFORMAT_U8)
		{
			psMovcInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psMovcInst, IMOVC_U8);
			psMovcInst->u.psMovc->eTest = TEST_TYPE_GTE_ZERO;
			psMovcInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psMovcInst->asDest[0].uNumber = GetNextRegister(psState);
			psMovcInst->asDest[0].eFmt = UF_REGFORMAT_U8;
			psMovcInst->asArg[0] = *psHwSource;
			psMovcInst->asArg[1] = *psHwSource;
			psMovcInst->asArg[2] = psNegateInst->asDest[0];
			AppendInst(psState, psCodeBlock, psMovcInst);
			*psHwSource = psMovcInst->asDest[0];			
		}
		else
		{
			psMovcInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psMovcInst, IMOVC_C10);
			psMovcInst->u.psMovc->eTest = TEST_TYPE_GTE_ZERO;
			psMovcInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psMovcInst->asDest[0].uNumber = GetNextRegister(psState);
			psMovcInst->asDest[0].eFmt = UF_REGFORMAT_C10;
			psMovcInst->asArg[0] = *psHwSource;
			psMovcInst->asArg[1] = *psHwSource;
			psMovcInst->asArg[2] = psNegateInst->asDest[0];
			AppendInst(psState, psCodeBlock, psMovcInst);
			*psHwSource = psMovcInst->asDest[0];
		}
		
	}
	if (bySrcMod & UFREG_SOURCE_NEGATE) 
	{
		PINST	psNegateInst;

		/*
			SOPWM	rDest = 0 - rDest
		*/
		psNegateInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psNegateInst, ISOPWM);
		psNegateInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, uMask);
		psNegateInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psNegateInst->asDest[0].uNumber = GetNextRegister(psState);
		psNegateInst->asDest[0].eFmt = UF_REGFORMAT_C10;
		psNegateInst->asArg[0].uType = USEASM_REGTYPE_IMMEDIATE;
		psNegateInst->asArg[0].uNumber = 0;
		psNegateInst->asArg[0].eFmt = UF_REGFORMAT_U8;
		psNegateInst->asArg[1] = *psHwSource;
		psNegateInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
		psNegateInst->u.psSopWm->bComplementSel1 = IMG_FALSE;
		psNegateInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
		psNegateInst->u.psSopWm->bComplementSel2 = IMG_TRUE;
		psNegateInst->u.psSopWm->uCop = psNegateInst->u.psSopWm->uAop = USEASM_INTSRCSEL_SUB;
		AppendInst(psState, psCodeBlock, psNegateInst);

		*psHwSource = psNegateInst->asDest[0];
	}
}

IMG_INTERNAL
IMG_UINT32 CheckDuplicateChannel(PUNIFLEX_INST	psInst,
								 IMG_UINT32		uChan)
/*****************************************************************************
 FUNCTION	: CheckDuplicateChannel

 PURPOSE	: Check if the value for a previous channel of the result of a
			  complex op instruction is the same as the current channel.

 PARAMETERS	: psInst			- Instruction to check.
			  uChan				- Channel to check.

 RETURNS	: The duplicated channel.
*****************************************************************************/
{
	IMG_UINT32	uPrevChan;

	for (uPrevChan = 0; uPrevChan < uChan; uPrevChan++)
	{
		if (
				(psInst->sDest.u.byMask & (1U << uPrevChan)) != 0 &&
				EXTRACT_CHAN(psInst->asSrc[0].u.uSwiz, uPrevChan) == EXTRACT_CHAN(psInst->asSrc[0].u.uSwiz, uChan)
		   )
		{
			return uPrevChan;
		}
	}
	return uChan;
}

static IMG_VOID ConvertScalarInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertScalarInstructionC10

 PURPOSE	: Convert an input scalar instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32	uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32	uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	IMG_UINT32	uChan;
	IMG_UINT32	uSourceChan;
	IMG_BOOL	bIgnoreSwiz;
	IMG_UINT32	uSourceMod;
	IOPCODE		eHwOpcode;
	IMG_UINT32	auDestChan[CHANNELS_PER_INPUT_REGISTER];
	IMG_UINT32	auDestComponent[CHANNELS_PER_INPUT_REGISTER];
	ARG			asResultDest[CHANNELS_PER_INPUT_REGISTER] = {USC_ARG_DEFAULT_VALUE, 
															 USC_ARG_DEFAULT_VALUE, 
															 USC_ARG_DEFAULT_VALUE, 
															 USC_ARG_DEFAULT_VALUE};
	
	/* Nothing to do if the destination isn't updated. */
	if (psSrc->sDest.u.byMask == 0)
	{
		return;
	}

	/* Select the hardware opcode. */
	switch (psSrc->eOpCode)
	{
		case UFOP_RECIP: eHwOpcode = IFRCP; break;
		case UFOP_RSQRT: eHwOpcode = IFRSQ; break;
		case UFOP_EXP: eHwOpcode = IFEXP; break;
		case UFOP_LOG: eHwOpcode = IFLOG; break;
		#if defined(SUPPORT_SGX545)
		case UFOP_SQRT: eHwOpcode = IFSQRT; break;
		#endif /* defined(SUPPORT_SGX545) */
		default: return;
	}

	/*
		We can do a negate or abs directly in the instruction.
	*/
	uSourceMod = psSrc->asSrc[0].byMod & ~(UFREG_SOURCE_NEGATE | UFREG_SOURCE_ABS);
	
	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		if (psSrc->sDest.u.byMask & (1U << uChan))
		{
			PINST		psInst;
			IMG_UINT32	uSourceComponent;

			/*
				Does this channel have the same value as a previous channel?
			*/
			if ((auDestChan[uChan] = CheckDuplicateChannel(psSrc, uChan)) < uChan)
			{
				continue;
			}
			
			/*
				Can we use the component select in the complex op instruction.
			*/
			if (CanOverrideSwiz(&psSrc->asSrc[0]))
			{
				uSourceChan = EXTRACT_CHAN(psSrc->asSrc[0].u.uSwiz, uChan);
				bIgnoreSwiz = IMG_TRUE;
			}
			else
			{
				uSourceChan = uChan;
				bIgnoreSwiz = IMG_FALSE;
			}

			psInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psInst, eHwOpcode);

			/* 
				The scalar instruction writes the source channel and zeros the other channels so write to
				a temporary so we can do masking.
			*/
			psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psInst->asDest[0].uNumber = GetNextRegister(psState);
			psInst->asDest[0].eFmt = UF_REGFORMAT_C10;
			asResultDest[uChan] = psInst->asDest[0];

			/* Get the source register. */
			GetSourceC10(psState, 
						 psCodeBlock, 
						 &psSrc->asSrc[0], 
						 (IMG_UINT8)uSourceMod, 
						 &psInst->asArg[0], 
						 1 << uSourceChan, 
						 bIgnoreSwiz, 
						 IMG_FALSE, 
						 psSrc->asSrc[0].eFormat);
			
			if(psInst->asArg[0].eFmt == UF_REGFORMAT_U8)
			{
				ConvertU8ArgToC10(psState, 
								  psCodeBlock, 
								  &(psInst->asArg[0]), 
								  &(psInst->asArg[0]), 
								  USC_DESTMASK_FULL);
			}
			uSourceComponent = ConvertInputChannelToIntermediate(psState, uSourceChan);
			SetComponentSelect(psState, psInst, 0 /* uArgIdx */, uSourceComponent);

			/* No format conversion. */
			SetBit(psInst->auFlag, INST_TYPE_PRESERVE, 1);

			/* Set source modifiers. */
			if (psSrc->asSrc[0].byMod & UFREG_SOURCE_NEGATE)
			{
				psInst->u.psFloat->asSrcMod[0].bNegate = IMG_TRUE;
			}
			if (psSrc->asSrc[0].byMod & UFREG_SOURCE_ABS)
			{
				psInst->u.psFloat->asSrcMod[0].bAbsolute = IMG_TRUE;
			}

			/* Insert the new instruction in the current block. */
			AppendInst(psState, psCodeBlock, psInst);

			/* Convert C10 result to required U8 format. */
			if(psSrc->sDest.eFormat == UF_REGFORMAT_U8)
			{
				ConvertC10ArgToU8(psState, psCodeBlock, &(psInst->asDest[0]), &(asResultDest[uChan]), USC_DESTMASK_FULL);
			}

			/*
				The component the destination is produced in is the same as the source component.
			*/
			auDestComponent[uChan] = uSourceComponent;
		}
	}

	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		if (psSrc->sDest.u.byMask & (1U << uChan))
		{
			PINST		psPackInst;
			IMG_UINT32	uDestChan = auDestChan[uChan];

			/* Move the result into the real destination. */
			psPackInst = AllocateInst(psState, IMG_NULL);
			if(psSrc->sDest.eFormat == UF_REGFORMAT_U8)
			{
				SetOpcode(psState, psPackInst, IPCKU8U8);
			}
			else
			{
				SetOpcode(psState, psPackInst, IPCKC10C10);
			}
			psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
			GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
			GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);
			psPackInst->asArg[0] = asResultDest[uDestChan];
			SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, auDestComponent[uDestChan]);
			psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psPackInst->asArg[1].uNumber = 0;
			AppendInst(psState, psCodeBlock, psPackInst);

			/* Check for the last channel. */
			if ((psSrc->sDest.u.byMask >> (uChan + 1)) == 0)
			{
				/* Do any destination modifiers. */
				GenerateDestModC10(psState, psCodeBlock, &psPackInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);
			}
		}
	}

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}
}

static IMG_VOID ConvertDotProductInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertDotProductInstructionC10
    
 PURPOSE	: Convert an input DOT2ADD/DOT3/DOT4 instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.
			  
 RETURNS	: None.
*****************************************************************************/
{
	PINST	psInst;
	IMG_BOOL bDot3 = (psSrc->eOpCode == UFOP_DOT3) ? IMG_TRUE : IMG_FALSE;
	IMG_BOOL bApplyMask = IMG_FALSE;
	IMG_UINT32 uPredType = psSrc->uPredicate & UF_PRED_COMP_MASK;
	IMG_UINT32 uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32 uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;

	psInst = AllocateInst(psState, IMG_NULL);

	SetOpcode(psState, psInst, IFPDOT);

	/*
		Check if we need to use a temporary destination.
	*/
	if (uPredType != UF_PRED_XYZW && psSrc->sDest.u.byMask == USC_DESTMASK_FULL)
	{
		GetDestinationC10(psState, &psSrc->sDest, &psInst->asDest[0]);
	}
	else
	{
		psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psInst->asDest[0].uNumber = GetNextRegister(psState);
		if(psSrc->sDest.eFormat == UF_REGFORMAT_U8)
		{
			psInst->asDest[0].eFmt = UF_REGFORMAT_U8;
		}
		else
		{
			psInst->asDest[0].eFmt = UF_REGFORMAT_C10;
		}
		bApplyMask = IMG_TRUE;
	}

	if (psSrc->eOpCode == UFOP_DOT4)
	{
		psInst->u.psDot34->uVecLength = 4;
	}
	else
	{
		ASSERT(psSrc->eOpCode == UFOP_DOT3 || psSrc->eOpCode == UFOP_DOT2ADD);
		psInst->u.psDot34->uVecLength = 3;
	}

	if (!bApplyMask && uPredType != UF_PRED_NONE)
	{
		GetInputPredicateInst(psState, psInst, psSrc->uPredicate, 0);
	}
	if (psSrc->eOpCode == UFOP_DOT2ADD)
	{
		PINST			psMoveInst;
		UF_REGFORMAT	eDstFmt;
		UF_REGFORMAT	eSrc0Fmt;
		IMG_UINT32		uTempSrc1 = GetNextRegister(psState);
		IMG_UINT32		uTempSrc2 = GetNextRegister(psState);
		ARG				sSrc0, sSrc2;

		GetSourceC10(psState, 
					 psCodeBlock, 
					 &psSrc->asSrc[0], 
					 psSrc->asSrc[0].byMod, 
					 &sSrc0, 
					 USC_RED_CHAN_MASK | USC_GREEN_CHAN_MASK, 
					 IMG_FALSE, 
					 IMG_FALSE, 
					 psSrc->asSrc[0].eFormat);
		GetSourceC10(psState, 
					 psCodeBlock,
					 &psSrc->asSrc[2], 
					 psSrc->asSrc[2].byMod, 
					 &sSrc2, 
					 USC_BLUE_CHAN_MASK, 
					 IMG_FALSE, 
					 IMG_FALSE, 
					 psSrc->asSrc[2].eFormat);

		if (sSrc0.eFmt == UF_REGFORMAT_C10 || sSrc2.eFmt == UF_REGFORMAT_C10)
		{
			if (sSrc0.eFmt == UF_REGFORMAT_U8)
			{
				ConvertU8ArgToC10(psState, psCodeBlock, &sSrc0, &sSrc0, USC_RED_CHAN_MASK | USC_GREEN_CHAN_MASK);
			}
			if (sSrc2.eFmt == UF_REGFORMAT_U8)
			{
				ConvertU8ArgToC10(psState, psCodeBlock, &sSrc2, &sSrc2, USC_BLUE_CHAN_MASK);
			}
			eSrc0Fmt = UF_REGFORMAT_C10;
		}
		else
		{
			eSrc0Fmt = UF_REGFORMAT_U8;
		}

		/*
			Force src2.blue into the src1 blue channel.
		*/
		psMoveInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psMoveInst, IMOV);
		psMoveInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psMoveInst->asDest[0].uNumber = uTempSrc1;
		psMoveInst->asDest[0].eFmt = eSrc0Fmt;
		psMoveInst->asArg[0] = sSrc0;
		AppendInst(psState, psCodeBlock, psMoveInst);

		psMoveInst = AllocateInst(psState, IMG_NULL);
		if (eSrc0Fmt == UF_REGFORMAT_U8)
		{
			SetOpcode(psState, psMoveInst, IPCKU8U8);
		}
		else
		{
			SetOpcode(psState, psMoveInst, IPCKC10C10);
		}
		psMoveInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << UFREG_DMASK_B_SHIFT);
		psMoveInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psMoveInst->asDest[0].uNumber = uTempSrc1;
		psMoveInst->asDest[0].eFmt = eSrc0Fmt;
		psMoveInst->asArg[0] = sSrc2;
		SetPCKComponent(psState, psMoveInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, USC_BLUE_CHAN));
		psMoveInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
		psMoveInst->asArg[1].uNumber = 0;
		AppendInst(psState, psCodeBlock, psMoveInst);

		psInst->asArg[0] = psMoveInst->asDest[0];

		/*
			Force one into the src2 blue channel.
		*/
		psMoveInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psMoveInst, IMOV);
		psMoveInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psMoveInst->asDest[0].uNumber = uTempSrc2;
		GetSourceC10(psState, 
					 psCodeBlock, 
					 &psSrc->asSrc[1], 
					 psSrc->asSrc[1].byMod, 
					 &psMoveInst->asArg[0], 
					 USC_RED_CHAN_MASK | USC_GREEN_CHAN_MASK, 
					 IMG_FALSE, 
					 IMG_FALSE, 
					 psSrc->asSrc[1].eFormat);
		if(psMoveInst->asArg[0].eFmt == UF_REGFORMAT_U8)
		{
			psMoveInst->asDest[0].eFmt = UF_REGFORMAT_U8;
			eDstFmt = UF_REGFORMAT_U8;
		}
		else
		{
			psMoveInst->asDest[0].eFmt = UF_REGFORMAT_C10;
			eDstFmt = UF_REGFORMAT_C10;
		}
		AppendInst(psState, psCodeBlock, psMoveInst);

		ConvertF32ImmediateToC10(psState, psCodeBlock, uTempSrc2, USC_BLUE_CHAN, eDstFmt, UFREG_SWIZ_1);

		psInst->asArg[1] = psMoveInst->asDest[0];
		if(psMoveInst->asDest[0].eFmt != UF_REGFORMAT_U8)
		{
			psInst->asArg[1].eFmt = UF_REGFORMAT_C10;
		}
	}
	else
	{
		/* If both source parameters have _bias generate respective U8DOT*OFF instruction and remove bias */
		if( ((psSrc->asSrc[0].byMod & UFREG_SMOD_MASK) == UFREG_SMOD_BIAS) &&
		    ((psSrc->asSrc[1].byMod & UFREG_SMOD_MASK) == UFREG_SMOD_BIAS)  )
		{
			psSrc->asSrc[0].byMod = (IMG_BYTE)(psSrc->asSrc[0].byMod & ~((unsigned)UFREG_SMOD_BIAS));
			psSrc->asSrc[1].byMod = (IMG_BYTE)(psSrc->asSrc[1].byMod & ~((unsigned)UFREG_SMOD_BIAS));

			psInst->u.psDot34->bOffset = IMG_TRUE;
		}

		GetSourceC10(psState, 
					 psCodeBlock, 
					 &psSrc->asSrc[0], 
					 psSrc->asSrc[0].byMod, 
					 &psInst->asArg[0], 
					 bDot3 ? USC_XYZ_CHAN_MASK : USC_XYZW_CHAN_MASK, 
					 IMG_FALSE, 
					 IMG_TRUE, 
					 psSrc->asSrc[0].eFormat);
		GetSourceC10(psState, 
					 psCodeBlock, 
					 &psSrc->asSrc[1], 
					 psSrc->asSrc[1].byMod, 
					 &psInst->asArg[1],
					 bDot3 ? USC_XYZ_CHAN_MASK : USC_XYZW_CHAN_MASK, 
					 IMG_FALSE, 
					 IMG_TRUE, 
					 psSrc->asSrc[1].eFormat);
	}

	/* If multiplying, stop GenerateDestModC10 adding unnecessary scaling instructions */
	if (uScale <= UFREG_DMOD_SCALEMUL8)
	{
		psInst->u.psDot34->uDot34Scale = uScale;
		uScale = 0;
	}
	
	AppendInst(psState, psCodeBlock, psInst);

	/* Do any destination modifiers. */
	GenerateDestModC10(psState, psCodeBlock, &psInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);

	if (bApplyMask)
	{
		if (uPredType == UF_PRED_XYZW)
		{
			IMG_UINT32	uChan;

			for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
			{
				if (psSrc->sDest.u.byMask & (1U << uChan))
				{
					PINST	psPackInst;

					psPackInst = AllocateInst(psState, IMG_NULL);
					SetOpcode(psState, psPackInst, IPCKC10C10);
					GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
					GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);
					psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
					psPackInst->asArg[0] = psInst->asDest[0];
					SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uChan));
					psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
					psPackInst->asArg[1].uNumber = 0;
					AppendInst(psState, psCodeBlock, psPackInst);
				}
			}
		}
		else
		{
			PINST	psSopwmInst;

			psSopwmInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psSopwmInst, ISOPWM);
			psSopwmInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);
			GetDestinationC10(psState, &psSrc->sDest, &psSopwmInst->asDest[0]);
			GetInputPredicateInst(psState, psSopwmInst, psSrc->uPredicate, 0);
			psSopwmInst->asArg[0] = psInst->asDest[0];
			psSopwmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psSopwmInst->asArg[1].uNumber = 0;
			psSopwmInst->u.psSopWm->uAop = psSopwmInst->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
			psSopwmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
			psSopwmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
			psSopwmInst->u.psSopWm->uSel1 = psSopwmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			AppendInst(psState, psCodeBlock, psSopwmInst);
		}
	}

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}
}

#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
static IMG_VOID ConvertFloatTempToC10_Vec(PINTERMEDIATE_STATE	psState,
										  PCODEBLOCK			psCodeBlock,
										  PUNIFLEX_INST			psInputInst,
										  IMG_UINT32			uFloatTemp,
										  UF_REGFORMAT			eFloatFormat)
/*****************************************************************************
 FUNCTION	: ConvertFloatTempToC10_Vec
    
 PURPOSE	: Convert an F16/F32 vec4 to C10 format and write it to the destination
			  of a C10 input instruction.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psInputInst		- Instruction to convert.
			  uFloatTemp		- Number of the temporary register containing
								the F16/F32 vec4.
			  eFloatFormat		- Format of the vec4.
			  
 RETURNS	: None.
*****************************************************************************/
{
	PINST		psConvertFromFloatInst;

	psConvertFromFloatInst = AllocateInst(psState, NULL);

	if (psInputInst->sDest.eFormat == UF_REGFORMAT_C10)
	{
		SetOpcode(psState, psConvertFromFloatInst, IVPCKC10FLT);
	}
	else
	{
		ASSERT(psInputInst->sDest.eFormat == UF_REGFORMAT_U8);
		SetOpcode(psState, psConvertFromFloatInst, IVPCKU8FLT);
	}

	psConvertFromFloatInst->u.psVec->bPackScale = IMG_TRUE;

	GetDestinationC10(psState, &psInputInst->sDest, &psConvertFromFloatInst->asDest[0]);

	psConvertFromFloatInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psInputInst->sDest.u.byMask);

	SetupTempVecSource(psState, psConvertFromFloatInst, 0 /* uSrcIdx */, uFloatTemp, eFloatFormat);

	psConvertFromFloatInst->u.psVec->auSwizzle[0] = USEASM_SWIZZLE(X, Y, Z, W);

	AppendInst(psState, psCodeBlock, psConvertFromFloatInst);
}

static IMG_VOID ConvertFloatOnlyInstructionC10_Vec(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psInputInst)
/*****************************************************************************
 FUNCTION	: ConvertFloatOnlyInstructionC10_Vec
    
 PURPOSE	: Convert a FRC/DSX/DSY instruction to the intermediate format on
			  cores which support vector instructions.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psInputSrc		- Instruction to convert.
			  
 RETURNS	: None.
*****************************************************************************/
{
	ARG			sInput;
	IMG_UINT32	uSwiz;
	IMG_UINT32	uSrcMask;
	IMG_BOOL	bIgnoreSwiz;
	PINST		psConvertToFloatInst;
	PINST		psFloatOpInst;
	IMG_UINT32	uConvertTemp;

	if (CanOverrideSwiz(&psInputInst->asSrc[0]))
	{
		bIgnoreSwiz = IMG_TRUE;
		uSwiz = psInputInst->asSrc[0].u.uSwiz;
		uSrcMask = SwizzleMask(psInputInst->asSrc[0].u.uSwiz, psInputInst->sDest.u.byMask);
	}
	else
	{
		bIgnoreSwiz = IMG_FALSE;
		uSwiz = UFREG_SWIZ_RGBA;
		uSrcMask = psInputInst->sDest.u.byMask;
	}

	/* Get the C10 format source. */
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psInputInst->asSrc[0], 
				 psInputInst->asSrc[0].byMod, 
				 &sInput, 
				 uSrcMask, 
				 bIgnoreSwiz, 
				 IMG_FALSE, 
				 psInputInst->asSrc[0].eFormat);

	/*
		Get a temporary register for use during the calculation.
	*/
	uConvertTemp = GetNextRegister(psState);

	/*
		Convert the source data to F16 format.
	*/
	psConvertToFloatInst = AllocateInst(psState, NULL);

	if (sInput.eFmt == UF_REGFORMAT_C10)
	{
		SetOpcode(psState, psConvertToFloatInst, IVPCKFLTC10);
	}
	else
	{
		ASSERT(sInput.eFmt == UF_REGFORMAT_U8);
		SetOpcode(psState, psConvertToFloatInst, IVPCKFLTU8);
	}

	psConvertToFloatInst->u.psVec->bPackScale = IMG_TRUE;

	psConvertToFloatInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psConvertToFloatInst->asDest[0].uNumber = uConvertTemp;
	psConvertToFloatInst->asDest[0].eFmt = UF_REGFORMAT_F16;

	psConvertToFloatInst->asArg[0] = sInput;

	psConvertToFloatInst->u.psVec->auSwizzle[0] = ConvertSwizzle(psState, uSwiz);
	psConvertToFloatInst->u.psVec->aeSrcFmt[0] = UF_REGFORMAT_C10;

	AppendInst(psState, psCodeBlock, psConvertToFloatInst);

	/*
		Do the main operation on the F16 format data.
	*/
	psFloatOpInst = AllocateInst(psState, NULL);
	switch (psInputInst->eOpCode)
	{
		case UFOP_DSX: SetOpcode(psState, psFloatOpInst, IVDSX); break;
		case UFOP_DSY: SetOpcode(psState, psFloatOpInst, IVDSY); break;
		case UFOP_FRC: SetOpcode(psState, psFloatOpInst, IVFRC); break;
		default: imgabort();
	}
	
	psFloatOpInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psFloatOpInst->asDest[0].uNumber = uConvertTemp;
	psFloatOpInst->asDest[0].eFmt = UF_REGFORMAT_F16;

	/* Source is the converted data. */
	SetupTempVecSource(psState, psFloatOpInst, 0 /* uSrcIdx */, uConvertTemp, UF_REGFORMAT_F16);
	psFloatOpInst->u.psVec->auSwizzle[0] = USEASM_SWIZZLE(X, Y, Z, W);

	if (psInputInst->eOpCode == UFOP_FRC)
	{
		/*
			FRC	X, Y -> FSUBFLR X, Y, Y
		*/
		SetupTempVecSource(psState, psFloatOpInst, 1 /* uSrcIdx */, uConvertTemp, UF_REGFORMAT_F16);
		psFloatOpInst->u.psVec->auSwizzle[1] = USEASM_SWIZZLE(X, Y, Z, W);
	}

	AppendInst(psState, psCodeBlock, psFloatOpInst);

	/*
		Convert the F16 format data back to C10.
	*/
	ConvertFloatTempToC10_Vec(psState, psCodeBlock, psInputInst, uConvertTemp, UF_REGFORMAT_F16);

	/* Do any destination modifiers. */
	ApplyDestModC10(psState, psCodeBlock, psInputInst);

	/* Store into an indexable temporary register. */
	if (psInputInst->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psInputInst->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psInputInst->sDest.eType == UFREG_TYPE_VSOUTPUT || psInputInst->sDest.eType == UFREG_TYPE_PSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psInputInst, &psInputInst->sDest);
	}
}
#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */

static IMG_VOID ConvertFloatOnlyInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertFloatInstructionC10
    
 PURPOSE	: Convert a FRC/DSX/DSY instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.
			  
 RETURNS	: None.
*****************************************************************************/
{
	ARG			sInput;
	IMG_UINT32	uChan;
	IMG_UINT32	uSrcMask;
	IMG_UINT32	uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32	uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	IMG_BOOL	bIgnoreSwiz;
	IMG_UINT32	uSwiz;

	if (CanOverrideSwiz(&psSrc->asSrc[0]))
	{
		bIgnoreSwiz = IMG_TRUE;
		uSwiz = psSrc->asSrc[0].u.uSwiz;
		uSrcMask = SwizzleMask(psSrc->asSrc[0].u.uSwiz, psSrc->sDest.u.byMask);
	}
	else
	{
		bIgnoreSwiz = IMG_FALSE;
		uSwiz = UFREG_SWIZ_RGBA;
		uSrcMask = psSrc->sDest.u.byMask;
	}

	/* Get the C10 format source. */
	GetSourceC10(psState, psCodeBlock, &psSrc->asSrc[0], psSrc->asSrc[0].byMod, &sInput, uSrcMask, bIgnoreSwiz, IMG_FALSE, psSrc->asSrc[0].eFormat);

	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		PINST		psPackInst, psGradInst;
		IMG_UINT32	uSrcChan = EXTRACT_CHAN(uSwiz, uChan);

		if ((psSrc->sDest.u.byMask & (1U << uChan)) == 0)
		{
			continue;
		}

		/* Convert the input register to float. */
		psPackInst = AllocateInst(psState, IMG_NULL);
		if(sInput.eFmt == UF_REGFORMAT_U8)
		{
			SetOpcode(psState, psPackInst, IUNPCKF32U8);
		}
		else
		{
			SetOpcode(psState, psPackInst, IUNPCKF32C10);
		}
		psPackInst->u.psPck->bScale = IMG_TRUE;
		psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psPackInst->asDest[0].uNumber = USC_TEMPREG_TEMPSRC + 4 + uChan;
		psPackInst->asArg[0] = sInput;
		SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uSrcChan));
		AppendInst(psState, psCodeBlock, psPackInst);

		/* Do the operation at F32 precision. */
		psGradInst = AllocateInst(psState, IMG_NULL);
		switch (psSrc->eOpCode)
		{
			case UFOP_DSX: SetOpcode(psState, psGradInst, IFDSX); break;
			case UFOP_DSY: SetOpcode(psState, psGradInst, IFDSY); break;
			case UFOP_FRC: SetOpcode(psState, psGradInst, IFSUBFLR); break;
			default: imgabort();
		}
		psGradInst->asDest[0] = psPackInst->asDest[0];
		psGradInst->asArg[0] = psPackInst->asDest[0];
		psGradInst->asArg[1] = psGradInst->asArg[0];
		AppendInst(psState, psCodeBlock, psGradInst);
	}

	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		PINST	psPackInst;

		if ((psSrc->sDest.u.byMask & (1U << uChan)) == 0)
		{
			continue;
		}

		/* Convert back to floating point */
		psPackInst = AllocateInst(psState, IMG_NULL);
		if(psSrc->sDest.eFormat == UF_REGFORMAT_U8)
		{
			SetOpcode(psState, psPackInst, IPCKU8F32);
		}
		else
		{
			SetOpcode(psState, psPackInst, IPCKC10F32);
		}
		psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
		psPackInst->u.psPck->bScale = IMG_TRUE;
		GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
		psPackInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
		psPackInst->asArg[0].uNumber = USC_TEMPREG_TEMPSRC + 4 + uChan;
		psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
		psPackInst->asArg[1].uNumber = 0;
		if ((psSrc->uPredicate & UF_PRED_COMP_MASK) != UF_PRED_NONE)
		{
			GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);
		}
		AppendInst(psState, psCodeBlock, psPackInst);

		if ((psSrc->sDest.u.byMask >> (uChan + 1)) == 0)
		{
			/* Do any destination modifiers. */
			GenerateDestModC10(psState, psCodeBlock, &psPackInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);
		}
	}

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}
}

static IMG_VOID ConvertLrpInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertLrpInstructionC10

 PURPOSE	: Convert an LRP instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
{
	PINST		psSop3Inst;
	IMG_UINT32	uPredType = psSrc->uPredicate & UF_PRED_COMP_MASK;
	IMG_BOOL	bSeperateMask = IMG_FALSE;
	IMG_UINT32	uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32	uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	IMG_UINT32	uSwizMask = MaskToSwiz(psSrc->sDest.u.byMask);
	IMG_BOOL	bSrc2AlphaSwizzle;

	psSop3Inst = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psSop3Inst, ISOP3);

	/*
		Check we need to use a temporary destination.
	*/
	if (uPredType != UF_PRED_XYZW && psSrc->sDest.u.byMask == USC_DESTMASK_FULL)
	{
		if (uPredType != UF_PRED_NONE)
		{
			GetInputPredicateInst(psState, psSop3Inst, psSrc->uPredicate, 0);
		}

		GetDestinationC10(psState, &psSrc->sDest, &psSop3Inst->asDest[0]);
	}
	else
	{
		psSop3Inst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psSop3Inst->asDest[0].uNumber = GetNextRegister(psState);
		psSop3Inst->asDest[0].eFmt = UF_REGFORMAT_C10;

		bSeperateMask = IMG_TRUE;
	}

	/*
		Check if we could do swizzles directly in the instruction.
	*/
	bSrc2AlphaSwizzle = IMG_FALSE;
	if (
			CanOverrideSwiz(&psSrc->asSrc[2]) &&
			(psSrc->asSrc[2].u.uSwiz & uSwizMask) == (UFREG_SWIZ_AAAA & uSwizMask)
	   )
	{
		bSrc2AlphaSwizzle = IMG_TRUE;
	}

	/*
		Get the sources. SOP3 does (1-S0)*S1+S0*S2 whereas the input LRP does S2*S0+(1-S2)*S1
	*/
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[0], 
				 psSrc->asSrc[0].byMod, 
				 &psSop3Inst->asArg[2], 
				 psSrc->sDest.u.byMask, 
				 IMG_FALSE, 
				 IMG_TRUE, 
				 psSrc->asSrc[0].eFormat);
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[1], 
				 psSrc->asSrc[1].byMod, 
				 &psSop3Inst->asArg[1], 
				 psSrc->sDest.u.byMask, 
				 IMG_FALSE, 
				 IMG_TRUE, 
				 psSrc->asSrc[1].eFormat);
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[2], 
				 psSrc->asSrc[2].byMod, 
				 &psSop3Inst->asArg[0], 
				 bSrc2AlphaSwizzle ? 8 : psSrc->sDest.u.byMask, 
				 bSrc2AlphaSwizzle, 
				 IMG_TRUE, 
				 psSrc->asSrc[2].eFormat);

	/*
		RGB = (1 - SRC0) * SRC1 + SRC0 * SRC2
	*/
	psSop3Inst->u.psSop3->uCOp = USEASM_INTSRCSEL_ADD;
	psSop3Inst->u.psSop3->uCSel1 = bSrc2AlphaSwizzle ? USEASM_INTSRCSEL_SRC0ALPHA : USEASM_INTSRCSEL_SRC0;
	psSop3Inst->u.psSop3->bComplementCSel1 = IMG_TRUE;
	psSop3Inst->u.psSop3->uCSel2 = bSrc2AlphaSwizzle ? USEASM_INTSRCSEL_SRC0ALPHA : USEASM_INTSRCSEL_SRC0;
	psSop3Inst->u.psSop3->bComplementCSel2 = IMG_FALSE;
	psSop3Inst->u.psSop3->bNegateCResult = IMG_FALSE;

	/*
		ALPHA = (1 - SRC0) * SRC1 + SRC0 * SRC2
	*/
	psSop3Inst->u.psSop3->uCoissueOp = USEASM_OP_ALRP;
	psSop3Inst->u.psSop3->uAOp = USEASM_INTSRCSEL_ADD;
	psSop3Inst->u.psSop3->uASel1 = USEASM_INTSRCSEL_SRC1ALPHA;
	psSop3Inst->u.psSop3->bComplementASel1 = IMG_FALSE;
	psSop3Inst->u.psSop3->uASel2 = USEASM_INTSRCSEL_SRC2ALPHA;
	psSop3Inst->u.psSop3->bComplementASel2 = IMG_FALSE;
	psSop3Inst->u.psSop3->bNegateAResult = IMG_FALSE;

	AppendInst(psState, psCodeBlock, psSop3Inst);

	/* Do any destination modifiers. */
	GenerateDestModC10(psState, psCodeBlock, &psSop3Inst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);

	/*
		Apply a predicate and/or a mask that needs to be done seperately.
	*/
	if (bSeperateMask)
	{
		if (uPredType == UF_PRED_XYZW)
		{
			IMG_UINT32	uChan;

			for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
			{
				if (psSrc->sDest.u.byMask & (1U << uChan))
				{
					PINST	psPackInst;

					psPackInst = AllocateInst(psState, IMG_NULL);
					SetOpcode(psState, psPackInst, IPCKC10C10);
					GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
					GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);
					psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
					psPackInst->asArg[0] = psSop3Inst->asDest[0];
					SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uChan));
					psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
					psPackInst->asArg[1].uNumber = 0;
					AppendInst(psState, psCodeBlock, psPackInst);
				}
			}
		}
		else
		{
			PINST	psSopwmInst;

			psSopwmInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psSopwmInst, ISOPWM);
			psSopwmInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);
			GetDestinationC10(psState, &psSrc->sDest, &psSopwmInst->asDest[0]);
			psSopwmInst->asArg[0] = psSop3Inst->asDest[0];
			psSopwmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psSopwmInst->asArg[1].uNumber = 0;
			psSopwmInst->u.psSopWm->uAop = psSopwmInst->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
			psSopwmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
			psSopwmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
			psSopwmInst->u.psSopWm->uSel1 = psSopwmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			AppendInst(psState, psCodeBlock, psSopwmInst);
		}
	}

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}
}

static IMG_VOID ConvertMadInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertMadInstructionC10
    
 PURPOSE	: Convert an MAD instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.
			  
 RETURNS	: None.
*****************************************************************************/
{
	PINST		psFpmaInst;
	IMG_UINT32	uPredType = psSrc->uPredicate & UF_PRED_COMP_MASK;
	IMG_BOOL	bSeperateMask = IMG_FALSE;
	IMG_UINT32	uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32	uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	IMG_BYTE	bySourceMod2;
	IMG_UINT32	uSwizMask = MaskToSwiz(psSrc->sDest.u.byMask);
	IMG_BOOL	pbAlphaSwiz[3];
	IMG_UINT32	uArg;

	psFpmaInst = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psFpmaInst, IFPMA);
	/*
		Check we need to use a temporary destination.
	*/
	if (uPredType != UF_PRED_XYZW && psSrc->sDest.u.byMask == USC_DESTMASK_FULL)
	{
		if (uPredType != UF_PRED_NONE)
		{
			GetInputPredicateInst(psState, psFpmaInst, psSrc->uPredicate, 0);
		}

		GetDestinationC10(psState, &psSrc->sDest, &psFpmaInst->asDest[0]);
	}
	else
	{
		psFpmaInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psFpmaInst->asDest[0].uNumber = GetNextRegister(psState);
		if(psSrc->sDest.eFormat == UF_REGFORMAT_U8)
		{
			psFpmaInst->asDest[0].eFmt = UF_REGFORMAT_U8;
		}
		else
		{
			psFpmaInst->asDest[0].eFmt = UF_REGFORMAT_C10;
		}

		bSeperateMask = IMG_TRUE;
	}


	/*
		Check if we could do swizzles directly in the instruction.
	*/
	for (uArg = 0; uArg < 3; uArg++)
	{
		pbAlphaSwiz[uArg] = IMG_FALSE;
		if (
				CanOverrideSwiz(&psSrc->asSrc[uArg]) &&
				(psSrc->asSrc[uArg].u.uSwiz & uSwizMask) == (UFREG_SWIZ_AAAA & uSwizMask)
		   )
		{
			pbAlphaSwiz[uArg] = IMG_TRUE;
		}
	}

	/*
		Negate modifier is only supported on source 2.
	*/
	bySourceMod2 = (IMG_BYTE)(psSrc->asSrc[2].byMod & ~UFREG_SOURCE_NEGATE);

	/*
		Get the sources. FPMA does S0+S1*S2 whereas the input MAD does S0*S1+S2
	*/
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[0], 
				 psSrc->asSrc[0].byMod, 
				 &psFpmaInst->asArg[1], 
				 pbAlphaSwiz[0] ? 8 : psSrc->sDest.u.byMask, 
				 pbAlphaSwiz[0], 
				 IMG_TRUE, 
				 psSrc->asSrc[0].eFormat);
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[1], 
				 psSrc->asSrc[1].byMod, 
				 &psFpmaInst->asArg[2], 
				 pbAlphaSwiz[1] ? 8 : psSrc->sDest.u.byMask, 
				 pbAlphaSwiz[1], 
				 IMG_TRUE, 
				 psSrc->asSrc[1].eFormat);
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[2], 
				 bySourceMod2, 
				 &psFpmaInst->asArg[0], 
		         pbAlphaSwiz[2] ? 8 : psSrc->sDest.u.byMask, 
				 pbAlphaSwiz[2], 
				 IMG_TRUE, 
				 psSrc->asSrc[2].eFormat);

	psFpmaInst->u.psFpma->bNegateSource0 = IMG_FALSE;
	if (psSrc->asSrc[2].byMod & UFREG_SOURCE_NEGATE)
	{
		psFpmaInst->u.psFpma->bNegateSource0 = IMG_TRUE;
	}

	psFpmaInst->u.psFpma->uCSel0 = pbAlphaSwiz[2] ? USEASM_INTSRCSEL_SRC0ALPHA : USEASM_INTSRCSEL_SRC0;
	psFpmaInst->u.psFpma->uASel0 = USEASM_INTSRCSEL_SRC0ALPHA;
	psFpmaInst->u.psFpma->uCSel1 = pbAlphaSwiz[0] ? USEASM_INTSRCSEL_SRC1ALPHA : USEASM_INTSRCSEL_SRC1;
	psFpmaInst->u.psFpma->uCSel2 = pbAlphaSwiz[1] ? USEASM_INTSRCSEL_SRC2ALPHA : USEASM_INTSRCSEL_SRC2;
	psFpmaInst->u.psFpma->bComplementCSel0 = psFpmaInst->u.psFpma->bComplementASel0 = IMG_FALSE;
	psFpmaInst->u.psFpma->bComplementCSel1 = psFpmaInst->u.psFpma->bComplementASel1 = IMG_FALSE;
	psFpmaInst->u.psFpma->bComplementCSel2 = psFpmaInst->u.psFpma->bComplementASel2 = IMG_FALSE;

	AppendInst(psState, psCodeBlock, psFpmaInst);

	/* Do any destination modifiers. */
	GenerateDestModC10(psState, psCodeBlock, &psFpmaInst->asDest[0], uSat, 
					   uScale, psSrc->sDest.u.byMask);

	/*
		Apply a predicate and/or a mask that needs to be done seperately.
	*/
	if (bSeperateMask)
	{
		if (uPredType == UF_PRED_XYZW)
		{
			IMG_UINT32	uChan;

			for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
			{
				if (psSrc->sDest.u.byMask & (1U << uChan))
				{
					PINST	psPackInst;

					psPackInst = AllocateInst(psState, IMG_NULL);
					SetOpcode(psState, psPackInst, IPCKC10C10);
					GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
					GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);
					psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
					psPackInst->asArg[0] = psFpmaInst->asDest[0];
					SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uChan));
					psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
					psPackInst->asArg[1].uNumber = 0;
					AppendInst(psState, psCodeBlock, psPackInst);
				}
			}
		}
		else
		{
			PINST	psSopwmInst;

			psSopwmInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psSopwmInst, ISOPWM);
			psSopwmInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);
			GetDestinationC10(psState, &psSrc->sDest, &psSopwmInst->asDest[0]);
			GetInputPredicateInst(psState, psSopwmInst, psSrc->uPredicate, 0);
			psSopwmInst->asArg[0] = psFpmaInst->asDest[0];
			psSopwmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psSopwmInst->asArg[1].uNumber = 0;
			psSopwmInst->u.psSopWm->uAop = psSopwmInst->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
			psSopwmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
			psSopwmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
			psSopwmInst->u.psSopWm->uSel1 = psSopwmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			AppendInst(psState, psCodeBlock, psSopwmInst);
		}
	}

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}
}

static IMG_VOID ConvertVectorTwoArgInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertVectorTwoArgInstructionC10

 PURPOSE	: Convert an input vector instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32 uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32 uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	PINST psSopWm;
	IMG_UINT32 uPredType = psSrc->uPredicate & UF_PRED_COMP_MASK;
	IMG_BOOL bSeperateMask = IMG_FALSE;
	IMG_UINT32 uSwizMask = MaskToSwiz(psSrc->sDest.u.byMask);
	IMG_BOOL bSrc1AlphaSwiz = IMG_FALSE, bSrc2AlphaSwiz = IMG_FALSE;
	IMG_BYTE bySMod0, bySMod1;
	IMG_UINT32 uOp, uSrc1, uSrc2;
	UF_OPCODE eOpCode = psSrc->eOpCode;
	IMG_BOOL bComplementSel1 = IMG_FALSE;

	bySMod0 = psSrc->asSrc[0].byMod;
	bySMod1 = psSrc->asSrc[1].byMod;

	/*
		Check if we can implement negate modifiers directly in the instruction.
	*/
	uOp = USEASM_INTSRCSEL_ADD;
	uSrc1 = 0;
	uSrc2 = 1;
	if (eOpCode == UFOP_ADD)
	{
		if (bySMod1 & UFREG_SOURCE_NEGATE)
		{
			uOp = USEASM_INTSRCSEL_SUB;
			bySMod1 &= ~UFREG_SOURCE_NEGATE;
		}
		else if (bySMod0 & UFREG_SOURCE_NEGATE)
		{
			uOp = USEASM_INTSRCSEL_SUB;
			bySMod0 &= ~UFREG_SOURCE_NEGATE;
			uSrc1 = 1;
			uSrc2 = 0;
		}
	}

	if (eOpCode == UFOP_MUL)
	{
		/*
			Check if we can do an alpha-replicate modifier directly in the instruction.
		*/
		if (
				CanOverrideSwiz(&psSrc->asSrc[0]) &&
				(psSrc->asSrc[0].u.uSwiz & uSwizMask) == (UFREG_SWIZ_AAAA & uSwizMask)
		   )
		{
			bSrc1AlphaSwiz = IMG_TRUE;
			uSrc1 = 1;
			uSrc2 = 0;
		}
		else if (
					CanOverrideSwiz(&psSrc->asSrc[0]) &&
					(psSrc->asSrc[1].u.uSwiz & uSwizMask) == (UFREG_SWIZ_AAAA & uSwizMask)
				)
		{
			bSrc2AlphaSwiz = IMG_TRUE;
		}

		/*
			Check if we can do a complement modifier directly in the instruction. This is 
			only available on the source referenced through SEL1.
		*/
		if (
				((bySMod0 & UFREG_SMOD_MASK) >> UFREG_SMOD_SHIFT) == UFREG_SMOD_COMPLEMENT &&
				!bSrc2AlphaSwiz
		   )
		{
			bComplementSel1 = IMG_TRUE;
			uSrc1 = 1;
			uSrc2 = 0;
			bySMod0 &= ~UFREG_SMOD_MASK;
		}
		else if (
					((bySMod1 & UFREG_SMOD_MASK) >> UFREG_SMOD_SHIFT) == UFREG_SMOD_COMPLEMENT &&
					!bSrc1AlphaSwiz
				)
		{
			bComplementSel1 = IMG_TRUE;
			bySMod1 &= ~UFREG_SMOD_MASK;
		}
	}

	psSopWm = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psSopWm, ISOPWM);

	/*
		If the instruction has a different predicate for each channel then do
		the write to the destination in seperate instructions.
	*/
	if (uPredType != UF_PRED_XYZW || g_abSingleBitSet[psSrc->sDest.u.byMask])
	{
		IMG_UINT32	uChan;

		GetDestinationC10(psState, &psSrc->sDest, &psSopWm->asDest[0]);

		if (uPredType != UF_PRED_NONE)
		{
			for (uChan = 0; (psSrc->sDest.u.byMask & (1U << uChan)) == 0; uChan++);

			GetInputPredicateInst(psState, psSopWm, psSrc->uPredicate, uChan);
		}
	}
	else
	{
		psSopWm->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psSopWm->asDest[0].uNumber = GetNextRegister(psState);
		if(psSrc->sDest.eFormat == UF_REGFORMAT_U8)
		{
			psSopWm->asDest[0].eFmt = UF_REGFORMAT_U8;
		}
		else
		{
			psSopWm->asDest[0].eFmt = UF_REGFORMAT_C10;
		}

		bSeperateMask = IMG_TRUE;
	}

	psSopWm->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[0], 
				 bySMod0, 
				 &psSopWm->asArg[uSrc1], 
				 bSrc1AlphaSwiz ? 8 : psSrc->sDest.u.byMask, 
				 bSrc1AlphaSwiz, 
				 IMG_TRUE, 
				 psSrc->asSrc[0].eFormat);
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[1], 
				 bySMod1, 
				 &psSopWm->asArg[uSrc2], 
				 bSrc2AlphaSwiz ? 8 : psSrc->sDest.u.byMask, 
				 bSrc2AlphaSwiz, 
				 IMG_TRUE, 
				 psSrc->asSrc[1].eFormat);
	switch (eOpCode)
	{
		case UFOP_ADD:
		{
			psSopWm->u.psSopWm->uCop = uOp;
			psSopWm->u.psSopWm->uAop = uOp;
			psSopWm->u.psSopWm->bComplementSel1 = psSopWm->u.psSopWm->bComplementSel2 = IMG_TRUE;
			psSopWm->u.psSopWm->uSel1 = psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			break;
		}
		case UFOP_MUL:
		{
			psSopWm->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
			psSopWm->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
			psSopWm->u.psSopWm->bComplementSel1 = bComplementSel1;
			psSopWm->u.psSopWm->bComplementSel2 = IMG_FALSE;
			if (bSrc1AlphaSwiz || bSrc2AlphaSwiz)
			{
				psSopWm->u.psSopWm->uSel1 = USEASM_INTSRCSEL_SRC2ALPHA;
				psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			}
			else
			{
				psSopWm->u.psSopWm->uSel1 = USEASM_INTSRCSEL_SRC2;
				psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			}
			break;
		}
		case UFOP_MIN:
		case UFOP_MAX:
		{
			psSopWm->u.psSopWm->uCop = (psSrc->eOpCode == UFOP_MIN) ? USEASM_INTSRCSEL_MIN : USEASM_INTSRCSEL_MAX;
			psSopWm->u.psSopWm->uAop = psSopWm->u.psSopWm->uCop;
			psSopWm->u.psSopWm->bComplementSel1 = psSopWm->u.psSopWm->bComplementSel2 = IMG_TRUE;
			psSopWm->u.psSopWm->uSel1 = psSopWm->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			break;
		}
		default:
		{
			imgabort();
		}
	}
	AppendInst(psState, psCodeBlock, psSopWm);

	/* Do any destination modifiers. */
	GenerateDestModC10(psState, psCodeBlock, &psSopWm->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);

	/*
		If the instruction has a different predicate per-channel then do individual
		updates of each channel.
	*/
	if (bSeperateMask)
	{
		IMG_UINT32	uChan;

		for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
		{
			if (psSrc->sDest.u.byMask & (1U << uChan))
			{
				PINST	psPackInst;

				psPackInst = AllocateInst(psState, IMG_NULL);
				if(psSopWm->asDest[0].eFmt == UF_REGFORMAT_U8)
				{
					SetOpcode(psState, psPackInst, IPCKU8U8);
				}
				else
				{
					SetOpcode(psState, psPackInst, IPCKC10C10);
				}
				GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
				GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);
				psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
				psPackInst->asArg[0] = psSopWm->asDest[0];
				SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uChan));
				psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psPackInst->asArg[1].uNumber = 0;
				AppendInst(psState, psCodeBlock, psPackInst);
			}
		}
	}

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}
}

static IMG_VOID ConvertMovaInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertMovaInstructionC10

 PURPOSE	: Convert an input MOVA instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
{
	PINST		psInst;
	IMG_UINT32	uChan;
	ARG			sC10Src;
	IMG_BOOL	bIgnoreSwiz;
	IMG_UINT32	uSwiz;
	IMG_UINT32	uSrcMask;

	if (CanOverrideSwiz(&psSrc->asSrc[0]))
	{
		bIgnoreSwiz = IMG_TRUE;
		uSwiz = psSrc->asSrc[0].u.uSwiz;
		uSrcMask = SwizzleMask(uSwiz, psSrc->sDest.u.byMask);
	}
	else
	{
		bIgnoreSwiz = IMG_FALSE;
		uSwiz = UFREG_SWIZ_NONE;
		uSrcMask = psSrc->sDest.u.byMask;
	}

	/* Get the c10 format source for the address offset. */
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[0], 
				 psSrc->asSrc[0].byMod, 
				 &sC10Src, 
				 uSrcMask, 
				 bIgnoreSwiz, 
				 IMG_FALSE, 
				 psSrc->asSrc[0].eFormat);

	for (uChan = 0; uChan < 4; uChan++)
	{
		if (psSrc->sDest.u.byMask & (1U << uChan))
		{
			IMG_UINT32	uSrcChan = EXTRACT_CHAN(uSwiz, uChan);
			IMG_UINT32	uPredSrc;
			ARG			sSrc;
			IMG_BOOL	bPredSrcNegate;

			GetInputPredicate(psState, &uPredSrc, &bPredSrcNegate, psSrc->uPredicate, uChan);

			InitInstArg(&sSrc);
			sSrc.uType = USEASM_REGTYPE_TEMP;
			sSrc.uNumber = USC_TEMPREG_TEMPSRC;
			sSrc.eFmt = UF_REGFORMAT_F32;

			/*
				Convert the address to floating point.
			*/
			psInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psInst, IUNPCKF32C10);
			psInst->u.psPck->bScale = IMG_TRUE;
			psInst->asDest[0] = sSrc;
			psInst->asArg[0] = sC10Src;	
			SetPCKComponent(psState, psInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uSrcChan));
			AppendInst(psState, psCodeBlock, psInst);

			/*
				Convert the address offset to a 16-bit integer.
			*/
			ConvertAddressValue(psState, 
								psCodeBlock, 
								USC_TEMPREG_ADDRESS + uChan,
								&sSrc,
								0 /* uSourceComponent */,
								IMG_FALSE /* bU8Src */,
								uPredSrc,
								bPredSrcNegate);
		}
	}
}

IMG_INTERNAL
IMG_VOID GetCMPTestType(PINTERMEDIATE_STATE	psState, 
					    PUNIFLEX_INST		psInst, 
						IMG_BOOL			bSrc0Neg, 
						IMG_BOOL			bSrc0Abs, 
						PTEST_TYPE			peTest, 
						IMG_PUINT32			puTrueSrc)
/*****************************************************************************
 FUNCTION	: GetCMPTestType

 PURPOSE	: Convert a instruction opcode (CMP or CMPLT) and source modifier
			  on source 0 to a MOVC test type.

 PARAMETERS	: psState			- Compiler state.
			  psInst			- Input instruction.
			  bSrc0Neg			- Source modifiers on the first source.
			  bSrc0Abs
			  peTest			- Returns the MOVC test type.
			  puTrueSrc			- If the test result has a fixed value then
								returns the source which is always chosen.

 RETURNS	: None.
*****************************************************************************/
{
	TEST_TYPE	eTest;
	IMG_UINT32	uTrueSrc;

	uTrueSrc = USC_UNDEF;
	if (psInst->eOpCode == UFOP_CMP)
	{
		if (bSrc0Abs)
		{
			if (!bSrc0Neg)
			{
				/* ABS(SRC0) >= 0 -> TRUE */
				eTest = TEST_TYPE_ALWAYS_TRUE;
				uTrueSrc = 1;
			}
			else
			{
				/* -ABS(SRC0) >= 0 -> ABS(SRC0) <= 0 -> SRC0 == 0 */
				eTest = TEST_TYPE_EQ_ZERO;
			}
		}
		else
		{
			/*
				Otherwise: SRC0 >= 0
			*/
			eTest = TEST_TYPE_GTE_ZERO;
		}
	}
	else
	{
		ASSERT(psInst->eOpCode == UFOP_CMPLT);

		if (bSrc0Abs)
		{
			if (!bSrc0Neg)
			{
				/* ABS(SRC0) < 0 -> FALSE */
				eTest = TEST_TYPE_ALWAYS_TRUE;
				uTrueSrc = 2;
			}
			else
			{
				/* -ABS(SRC0) < 0 -> ABS(SRC0) > 0 -> SRC0 != 0 */
				eTest = TEST_TYPE_NEQ_ZERO;
			}
		}
		else
		{
			/*
				Otherwise: SRC0 < 0
			*/
			eTest = TEST_TYPE_LT_ZERO;
		}
	}

	*peTest = eTest;
	*puTrueSrc = uTrueSrc;
}

static IMG_VOID ConvertComparisonInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertComparisonInstructionC10

 PURPOSE	: Convert an input comparison instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
{
	PINST psInst;
	IMG_UINT32 uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32 uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	IMG_BOOL bSrc0Neg, bSrc0Abs;
	ARG sSrc1 = USC_ARG_DEFAULT_VALUE;
	ARG sSrc2 = USC_ARG_DEFAULT_VALUE;
	IMG_UINT32	uPredType = psSrc->uPredicate & UF_PRED_COMP_MASK;
	IMG_BOOL bSeperateMask = IMG_FALSE;
	IMG_BOOL bSeperatePredicate;
	IMG_BYTE bySrc0Mod = psSrc->asSrc[0].byMod;
	IMG_BOOL bCanUseU8Movc = IMG_TRUE;
	TEST_TYPE eTest;
	IMG_UINT32 uTrueSrc;

	/*
		Extract the source modifiers from input source 0.
	*/
	bSrc0Neg = (psSrc->asSrc[0].byMod & UFREG_SOURCE_NEGATE) ? IMG_TRUE : IMG_FALSE;
	bSrc0Abs = (psSrc->asSrc[0].byMod & UFREG_SOURCE_ABS) ? IMG_TRUE : IMG_FALSE;

	if (!(bSrc0Neg && !bSrc0Abs))
	{
		bySrc0Mod &= ~(UFREG_SOURCE_NEGATE | UFREG_SOURCE_ABS);
	}

	/*
		Get the additional sources and apply any source modifiers.
	*/
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[1], 
				 psSrc->asSrc[1].byMod, 
				 &sSrc1, 
				 psSrc->sDest.u.byMask, 
				 IMG_FALSE, 
				 IMG_FALSE, 
				 psSrc->asSrc[1].eFormat);
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[2], 
				 psSrc->asSrc[2].byMod, 
				 &sSrc2, 
				 psSrc->sDest.u.byMask, 
				 IMG_FALSE, 
				 IMG_FALSE, 
				 psSrc->asSrc[2].eFormat);

	/* MOVC_U8 requires both sources in U8 format. */
	if((sSrc1.eFmt != UF_REGFORMAT_U8) || (sSrc2.eFmt != UF_REGFORMAT_U8))
	{
		bCanUseU8Movc = IMG_FALSE;
	}

	/* Both sources should be fetched in same formats. */
	if((sSrc1.eFmt == UF_REGFORMAT_U8) && (sSrc2.eFmt == UF_REGFORMAT_C10))
	{
		ConvertU8ArgToC10(psState, psCodeBlock, &sSrc1, &sSrc1, psSrc->sDest.u.byMask);
	}

	/* Both sources should be fetched in same formats. */
	if((sSrc2.eFmt == UF_REGFORMAT_U8) && (sSrc1.eFmt == UF_REGFORMAT_C10))
	{
		ConvertU8ArgToC10(psState, psCodeBlock, &sSrc2, &sSrc2, psSrc->sDest.u.byMask);
	}

	/*
		Check if we need to seperate out the application of the predicate.
	*/
	bSeperatePredicate = IMG_FALSE;
	if (psState->psTargetBugs->ui32Flags & SGX_BUG_FLAGS_FIX_HW_BRN_21713)
	{
		if (uPredType != UF_PRED_NONE)
		{
			bSeperatePredicate = IMG_TRUE;
		}
	}
	else
	{
		if (uPredType == UF_PRED_XYZW)
		{
			bSeperatePredicate = IMG_TRUE;
		}
	}

	/*
		Convert the instruction type (CMP or CMPLT) and the source modifier on
		source 0 to a MOVC test type.
	*/
	GetCMPTestType(psState, psSrc, bSrc0Neg, bSrc0Abs, &eTest, &uTrueSrc);

	/*
		Do test instruction itself.
	*/
	psInst = AllocateInst(psState, IMG_NULL);

	if (eTest == TEST_TYPE_ALWAYS_TRUE)
	{
		/* Just move the always chosen source into the destination. */
		SetOpcode(psState, psInst, IMOV);
		psInst->asArg[0] = (uTrueSrc == 1) ? sSrc1 : sSrc2;
	}
	else
	{
		if((psSrc->sDest.eFormat == UF_REGFORMAT_U8) && bCanUseU8Movc) 
		{
			SetOpcode(psState, psInst, IMOVC_U8);
		}
		else
		{
			SetOpcode(psState, psInst, IMOVC_C10);
		}

		psInst->u.psMovc->eTest = eTest;
		
		GetSourceC10(psState, 
					 psCodeBlock, 
					 &psSrc->asSrc[0], 
					 bySrc0Mod, 
					 &psInst->asArg[0], 
					 psSrc->sDest.u.byMask, 
					 IMG_FALSE, 
					 IMG_FALSE, 
					 psSrc->asSrc[0].eFormat);
			
		/* Get intermediate result in C10 format. */
		if((psInst->asArg[0].eFmt != UF_REGFORMAT_C10) && (!bCanUseU8Movc))
		{
			ConvertU8ArgToC10(psState, 
							  psCodeBlock, 
							  &psInst->asArg[0], 
							  &psInst->asArg[0], 
							  psSrc->sDest.u.byMask);
		}
	
		/*
			Copy the second two sources - depending on the result of the test on source 0
			one of them is moved into the destination.
		*/
		psInst->asArg[1] = sSrc1;
		psInst->asArg[2] = sSrc2;
	}

	if (!bSeperatePredicate && psSrc->sDest.u.byMask == USC_DESTMASK_FULL)
	{
		/* Get intermediate result in C10 format. */
		if((!bCanUseU8Movc) && (psSrc->sDest.eFormat == UF_REGFORMAT_U8))
		{
			psInst->asDest[0].eFmt = UF_REGFORMAT_C10;
			psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psInst->asDest[0].uNumber = GetNextRegister(psState);
		}
		else
		{
			GetDestinationC10(psState, &psSrc->sDest, &psInst->asDest[0]);
		}
		GetInputPredicateInst(psState, psInst, psSrc->uPredicate, 0);
	}
	else
	{
		psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psInst->asDest[0].uNumber =  GetNextRegister(psState);
		if((psSrc->sDest.eFormat == UF_REGFORMAT_U8) && bCanUseU8Movc)
		{
			psInst->asDest[0].eFmt = UF_REGFORMAT_U8;
		}
		else
		{
			if(psSrc->sDest.eFormat == UF_REGFORMAT_U8)
			{
				psInst->asDest[0].uNumber = GetNextRegister(psState);
			}
			psInst->asDest[0].eFmt = UF_REGFORMAT_C10;
		}
		bSeperateMask = IMG_TRUE;
	}

	AppendInst(psState, psCodeBlock, psInst);

	/* Do any destination modifiers. */
	GenerateDestModC10(psState, psCodeBlock, &psInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);

	if (bSeperateMask)
	{
		if (uPredType == UF_PRED_XYZW)
		{
			if(psSrc->sDest.eFormat != UF_REGFORMAT_U8)
			{
				IMG_UINT32	uChan;
				for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
				{
					if (psSrc->sDest.u.byMask & (1U << uChan))
					{
						PINST	psPackInst;
						psPackInst = AllocateInst(psState, IMG_NULL);
						SetOpcode(psState, psPackInst, IPCKC10C10);
						GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
						GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);
						psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
						psPackInst->asArg[0] = psInst->asDest[0];
						SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uChan));
						psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
						psPackInst->asArg[1].uNumber = 0;
						AppendInst(psState, psCodeBlock, psPackInst);
					}
				}
			}
			else
			{
				PINST psSopWmInst;
				psSopWmInst = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psSopWmInst, ISOPWM);
				GetDestinationC10(psState, &psSrc->sDest, &psSopWmInst->asDest[0]);
				GetInputPredicateInst(psState, psSopWmInst, psSrc->uPredicate, 0);
				psSopWmInst->asArg[0] = psInst->asDest[0];
				psSopWmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psSopWmInst->asArg[1].uNumber = 0;
				psSopWmInst->u.psSopWm->uCop = psSopWmInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
				psSopWmInst->u.psSopWm->uSel1 = psSopWmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psSopWmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
				psSopWmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
				psSopWmInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);
				AppendInst(psState, psCodeBlock, psSopWmInst);
			}
		}
		else
		{
			PINST	psSopwmInst;

			psSopwmInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psSopwmInst, ISOPWM);
			GetInputPredicateInst(psState, psSopwmInst, psSrc->uPredicate, 0);
			GetDestinationC10(psState, &psSrc->sDest, &psSopwmInst->asDest[0]);
			psSopwmInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);
			psSopwmInst->asArg[0] = psInst->asDest[0];
			psSopwmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psSopwmInst->asArg[1].uNumber = 0;
			psSopwmInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
			psSopwmInst->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
			psSopwmInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
			psSopwmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			psSopwmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
			psSopwmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
			AppendInst(psState, psCodeBlock, psSopwmInst);
		}
	}
	else
	{
		/* Conversion to U8 format is required. */
		if((psSrc->sDest.eFormat == UF_REGFORMAT_U8) && (!bCanUseU8Movc))
		{
			PINST psSopWmInst;
			psSopWmInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psSopWmInst, ISOPWM);
			GetDestinationC10(psState, &psSrc->sDest, &psSopWmInst->asDest[0]);
			psSopWmInst->asArg[0] = psInst->asDest[0];
			psSopWmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psSopWmInst->asArg[1].uNumber = 0;
			psSopWmInst->u.psSopWm->uCop = psSopWmInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
			psSopWmInst->u.psSopWm->uSel1 = psSopWmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			psSopWmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
			psSopWmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
			AppendInst(psState, psCodeBlock, psSopWmInst);
		}
	}

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}
}

#if defined(OUTPUT_USCHW)
static IMG_VOID ConvertTextureChannelC10(PINTERMEDIATE_STATE	psState,
										 PCODEBLOCK				psCodeBlock,
										 IMG_UINT32				uFormat,
										 PUNIFLEX_INST			psInputInst,
										 IMG_UINT32				uDestChan,
										 IMG_UINT32				uSrcRegType,
										 IMG_UINT32				uSrcRegNum,
										 IMG_UINT32				uSrcByteOffset)
/*****************************************************************************
 FUNCTION	: ConvertTextureChannelC10

 PURPOSE	: Generates code to convert a channel of a texture sample result.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  uFormat			- Format of the texture sample result.
			  psInputInst		- Input texture load instruction.
			  uDestChan			- Channel in the input instruction destination
								to write with the converted channel.
			  uSrcRegType		- Register containing the texture sample result.
			  uSrcRegNum
			  uSrcByteOffset	- Byte offset of the result within the register.

 RETURNS	: None.
*****************************************************************************/
{
	ARG		sF32Temp;
	PINST	psInst;

	/*
		Get a temporary register to hold the value of the texture channel
		converted to F32.
	*/
	InitInstArg(&sF32Temp);
	sF32Temp.uType = USEASM_REGTYPE_TEMP;
	sF32Temp.uNumber = GetNextRegister(psState);

	/*
		Generate instructions to convert the texture channel to F32.
	*/
	UnpackTextureChannelToF32(psState,
							  psCodeBlock,
							  uFormat,
							  &sF32Temp,
							  USC_PREDREG_NONE,
							  IMG_FALSE /* bPredSrcNeg */,
							  uSrcRegType,
							  uSrcRegNum,
							  uSrcByteOffset,
							  IMG_FALSE /* bIntegerChannels */);

	/*
		Convert the texture channel from F32 to C10.
	*/
	psInst = AllocateInst(psState, IMG_NULL);
	if (psInputInst->sDest.eFormat == UF_REGFORMAT_C10)
	{
		SetOpcode(psState, psInst, IPCKC10F32);
	}
	else
	{
		SetOpcode(psState, psInst, IPCKU8F32);
	}
	psInst->u.psPck->bScale = IMG_TRUE;

	/*
		Set the instruction destination to the intermediate register representing the
		input texture instruction's destination.
	*/
	psInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uDestChan);
	GetDestinationC10(psState, &psInputInst->sDest, &psInst->asDest[0]); 

	GetInputPredicateInst(psState, psInst, psInputInst->uPredicate, uDestChan);

	/*
		Set the first source to the texture result channel converted to F32.
	*/
	psInst->asArg[0] = sF32Temp;

	/*
		The second source is unreferenced.
	*/
	psInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
	psInst->asArg[1].uNumber = 0;
	psInst->asArg[1].eFmt = UF_REGFORMAT_U8;
			
	AppendInst(psState, psCodeBlock, psInst);
}

static IMG_VOID ConvertTextureChannelFromC10(PINTERMEDIATE_STATE	psState,
											 PCODEBLOCK				psCodeBlock,
											 PUNIFLEX_INST			psInputInst,
											 IMG_UINT32				uDestChan,
											 IMG_UINT32				uSrcRegType,
											 IMG_UINT32				uSrcRegNum,
											 IMG_UINT32				uSrcByteOffset)
/*****************************************************************************
 FUNCTION	: ConvertTextureChannelFromC10

 PURPOSE	: Generates code to convert a channel of a texture sample result
			  already in C10 format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psInputInst		- Input texture load instruction.
			  uDestChan			- Channel in the input instruction destination
								to write with the converted channel.
			  uSrcRegType		- Register containing the texture sample result.
			  uSrcRegNum
			  uSrcByteOffset	- Offset of the C10 channel within the register.

 RETURNS	: None.
*****************************************************************************/
{
	PINST	psInst;

	psInst = AllocateInst(psState, NULL);
	if (psInputInst->sDest.eFormat == UF_REGFORMAT_C10)
	{
		/*
			No format conversion required.
		*/
		SetOpcode(psState, psInst, IPCKC10C10);
	}
	else
	{
		/* Convert C10 -> U8 */
		SetOpcode(psState, psInst, ISOPWM);

		/*
			DEST = SRC1 * ONE + SRC2 * ZERO
		*/
		psInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
		psInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
		psInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
		psInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
		psInst->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
		psInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
	}

	/*
		Set the instruction destination to the intermediate register representing the
		input texture instruction's destination.
	*/
	psInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uDestChan);
	GetDestinationC10(psState, &psInputInst->sDest, &psInst->asDest[0]); 

	GetInputPredicateInst(psState, psInst, psInputInst->uPredicate, uDestChan);

	/*
		Set the first source to the result of the texture sample.
	*/
	psInst->asArg[0].uType = uSrcRegType;
	psInst->asArg[0].uNumber = uSrcRegNum;
	SetPCKComponent(psState, psInst, 0 /* uArg */, uSrcByteOffset);
	psInst->asArg[0].eFmt = UF_REGFORMAT_C10;

	/*
		The second source is  unused.
	*/
	psInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
	psInst->asArg[1].uNumber = 0;
	psInst->asArg[1].eFmt = UF_REGFORMAT_U8;

	AppendInst(psState, psCodeBlock, psInst);
}

#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
static IMG_VOID UnpackTextureC10Vec(PINTERMEDIATE_STATE		psState,
								    PCODEBLOCK				psCodeBlock,
									PSAMPLE_RESULT_LAYOUT	psSampleResultLayout,
								    PSAMPLE_RESULT			psSampleResult,
								    PUNIFLEX_INST			psInputInst,
								    IMG_UINT32				uMask)
/*****************************************************************************
 FUNCTION	: UnpackTextureC10Vec

 PURPOSE	: Generates code to unpack a texture to C10 on core which
			  support the vector instruction set.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  uTexture			- Number of the texture to unpack.
			  uSrcRegType		- Register type of the data to unpack.
			  uSrcRegNum		- Register number of the data to unpack.
			  psInputInst		- Texture load instruction.
			  uMask				- Mask of channels to unpack.

 RETURNS	: None.
*****************************************************************************/
{
	ARG		sF32Temp;

	/*
		Get a temporary register for the texture sample result in
		F32 format.
	*/
	InitInstArg(&sF32Temp);
	sF32Temp.uType = USEASM_REGTYPE_TEMP;
	sF32Temp.uNumber = GetNextRegister(psState);

	/*
		Unpack the texture sample result to F32 format.
	*/
	UnpackTextureFloatVec(psState,
						  psCodeBlock,
						  psSampleResultLayout,
						  psSampleResult,
						  &sF32Temp,
						  uMask);

	/*
		Convert the texture sample result in F32 format back to C10.
	*/
	ConvertFloatTempToC10_Vec(psState, psCodeBlock, psInputInst, sF32Temp.uNumber, UF_REGFORMAT_F32);
}
#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */

static IMG_VOID UnpackTextureC10(PINTERMEDIATE_STATE	psState,
								 PCODEBLOCK				psCodeBlock,
								 PSAMPLE_RESULT_LAYOUT	psSampleResultLayout,
								 PSAMPLE_RESULT			psSampleResult,
								 PUNIFLEX_INST			psInputInst)
/*****************************************************************************
 FUNCTION	: UnpackTextureC10

 PURPOSE	: Generates code to unpack a texture.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSampleResultLayout
								- Offsets/formats of the packed texture data.
			  psSampleResult	- Details of the temporary registers containing
								the packed texture data.
			  psInputInst		- Input texture sample.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32	uChan;
	IMG_UINT32	uMask =  psInputInst->sDest.u.byMask;

	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if (psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_VEC34)
	{
		UnpackTextureC10Vec(psState,
							psCodeBlock,
							psSampleResultLayout,
							psSampleResult,
							psInputInst,
							uMask);
		return;
	}
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	
	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		if (uMask & (1U << uChan))
		{
			IMG_UINT32				uSrcRegNum;
			IMG_UINT32				uSrcChanOffset;
			USC_CHANNELFORM			eSrcFormat;

			/*
				Get the location and format of the raw data for this
				channel of the texture sample result.
			*/
			GetTextureSampleChannelLocation(psState, 
											psSampleResultLayout, 
											psSampleResult, 
											uChan, 
											&eSrcFormat, 
											&uSrcRegNum, 
											#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
											NULL /* pbSrcIsVector */,
											#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
											&uSrcChanOffset);

			if (eSrcFormat == USC_CHANNELFORM_C10)
			{
				/*
					Convert from sample data already in C10
					format.
				*/
				ConvertTextureChannelFromC10(psState, 
											 psCodeBlock,
											 psInputInst, 
											 uChan,
											 USEASM_REGTYPE_TEMP,
											 uSrcRegNum,
											 uSrcChanOffset);
			}
			else
			{
				/*
					Convert from sample data in any other format.
				*/
				ConvertTextureChannelC10(psState, 
										 psCodeBlock,
										 eSrcFormat,
										 psInputInst,
										 uChan,
										 USEASM_REGTYPE_TEMP,
										 uSrcRegNum,
										 uSrcChanOffset);
			}
		}
	}
}
#endif /* #if defined(OUTPUT_USCHW) */

#if defined(OUTPUT_USCHW)
static IMG_BOOL IsIdentitySamplerSwizzle(PINTERMEDIATE_STATE psState, PSAMPLE_RESULT_LAYOUT psSampleResultLayout)
/*****************************************************************************
 FUNCTION	: IsIdentitySamplerSwizzle

 PURPOSE	: Check for a texture sample result which requires a swizzle
			  when unpacking.

 PARAMETERS	: psState			- Compiler state.
			  psSampleResultLayout
								- Details of the layout of the packed
								results of the texture sample.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32	uSwizzle;
	IMG_UINT32	uChan;

	ASSERT(psSampleResultLayout->uChanCount == CHANNELS_PER_INPUT_REGISTER);

	uSwizzle = 0;
	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		USC_CHANNELFORM			eFormat;
		PSAMPLE_RESULT_LOCATION	psChannel = &psSampleResultLayout->asChannelLocation[uChan];
		IMG_UINT32				uDestChan = ConvertInputChannelToIntermediate(psState, uChan);
		
		eFormat = psChannel->eFormat;
		if (eFormat == USC_CHANNELFORM_U8 && psChannel->uChanOffset != uDestChan)
		{
			return IMG_FALSE;
		}
	}

	return IMG_TRUE;
}

static IMG_VOID UnpackU8Texture(PINTERMEDIATE_STATE			psState,
								PCODEBLOCK					psCodeBlock,
								PUNIFLEX_INST				psInputInst,
								PSAMPLE_RESULT_LAYOUT		psSampleResultLayout,
								PSAMPLE_RESULT				psSampleResult)
/*****************************************************************************
 FUNCTION	: UnpackU8Texture

 PURPOSE	: Unpack an integer texture to C10.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psInputInst		- Texture load structure.
			  psRawResult		- Packed result of the texture sample.
			  u8Mask			- Masks of the channels of each format.
			  uZeroMask
			  uOneMask

 RETURNS	: None.
*****************************************************************************/
{
	PINST			psInst;
	ARG				sDest;
	UF_REGFORMAT	eDestFormat = GetRegisterFormat(psState, &psInputInst->sDest);
	IMG_UINT32		uUnpackMask;
	IMG_BOOL		bSwizzle;
	IMG_UINT32		uChan;
	UF_REGFORMAT	eRegFormat;
	IMG_UINT32		uRawResultRegNum;
	IMG_UINT32		uConvertedRawResult = USC_UNDEF;

	if (psSampleResultLayout->uChunkCount == 1)
	{
		uRawResultRegNum = psSampleResult->auRawDataPerChunk[0];
	}
	else
	{
		ASSERT(psSampleResultLayout->uChunkCount == 0);
		uRawResultRegNum = 0;
	}

	ASSERT(eDestFormat == UF_REGFORMAT_U8 || eDestFormat == UF_REGFORMAT_C10);
	eRegFormat = eDestFormat;

	psInst = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psInst, ISOPWM);
	if (
			IsIdentitySamplerSwizzle(psState, psSampleResultLayout) &&
			(psInputInst->uPredicate & UF_PRED_COMP_MASK) != UF_PRED_XYZW
	   )
	{
		GetDestinationC10(psState, &psInputInst->sDest, &sDest);
		sDest.eFmt = eRegFormat;
		uUnpackMask = ConvertInputWriteMaskToIntermediate(psState, psInputInst->sDest.u.byMask);
		bSwizzle = IMG_FALSE;
		GetInputPredicateInst(psState, psInst, psInputInst->uPredicate, 0);
	}
	else
	{
		InitInstArg(&sDest);
		sDest.uType = USEASM_REGTYPE_TEMP;
		sDest.uNumber = uConvertedRawResult = GetNextRegister(psState);
		sDest.eFmt = eRegFormat;
		uUnpackMask = USC_DESTMASK_FULL;
		bSwizzle = IMG_TRUE;
	}

	/*
		Copy the U8 channels.
	*/
	psInst->asDest[0] = sDest;
	psInst->auDestMask[0] = uUnpackMask;
	psInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
	psInst->asArg[0].uNumber = uRawResultRegNum;
	psInst->asArg[0].eFmt = UF_REGFORMAT_U8;
	psInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
	psInst->asArg[1].uNumber = 0;
	psInst->asArg[1].eFmt = UF_REGFORMAT_U8;
	psInst->u.psSopWm->uCop = psInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
	psInst->u.psSopWm->uSel1 = psInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
	psInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
	psInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
	AppendInst(psState, psCodeBlock, psInst);

	/*
		Swizzle and set selected channels to zero or one.
	*/
	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		PINST		psPackInst;

		if (psInputInst->sDest.u.byMask & (1U << uChan))
		{
			PSAMPLE_RESULT_LOCATION	psChannel = &psSampleResultLayout->asChannelLocation[uChan];

			/*
				If we copied the U8 channels in the SOPWM then there's no
				need to do it again.
			*/
			if (!bSwizzle && psChannel->eFormat == USC_CHANNELFORM_U8)
			{
				continue;
			}

			psPackInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psPackInst, INVALID_MAXARG);

			if (psChannel->eFormat == USC_CHANNELFORM_U8)
			{
				SetOpcode(psState, psPackInst,	
						  (eDestFormat == UF_REGFORMAT_C10) ? IPCKC10C10 : IPCKU8U8);

				psPackInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
				psPackInst->asArg[0].uNumber = uConvertedRawResult;
				SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, psChannel->uChanOffset);
				psPackInst->asArg[0].eFmt = eRegFormat;
			}
			else
			{
				if (eDestFormat == UF_REGFORMAT_C10)
				{
					SetOpcode(psState, psPackInst, ISOPWM);
					psPackInst->u.psSopWm->uCop = psPackInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
					psPackInst->u.psSopWm->uSel1 = psPackInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
					psPackInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
					psPackInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
				}
				else
				{
					SetOpcode(psState, psPackInst, IPCKU8U8);
				}

				psPackInst->asArg[0].uType		= USEASM_REGTYPE_IMMEDIATE;
				psPackInst->asArg[0].eFmt		= UF_REGFORMAT_U8;
				if (psChannel->eFormat == USC_CHANNELFORM_ONE)
				{
					psPackInst->asArg[0].uNumber	= USC_U8_VEC4_ONE;
				}
				else
				{
					ASSERT(psChannel->eFormat == USC_CHANNELFORM_ZERO);
					psPackInst->asArg[0].uNumber	= 0;
				}
			}

			GetDestinationC10(psState, &psInputInst->sDest, &psPackInst->asDest[0]); 
			GetInputPredicateInst(psState, psPackInst, psInputInst->uPredicate, uChan);
			psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);

			psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psPackInst->asArg[1].uNumber = 0;

			AppendInst(psState, psCodeBlock, psPackInst);
		}
	}
}
#endif /* #if defined(OUTPUT_USCHW) */

#if defined(OUTPUT_USCHW)
static
IMG_VOID UnpackTextureFixedPoint(PINTERMEDIATE_STATE	psState, 
								 PCODEBLOCK				psCodeBlock,
								 PUNIFLEX_INST			psInputInst, 
								 PSAMPLE_RESULT_LAYOUT	psSampleResultLayout,
								 PSAMPLE_RESULT			psSampleResult)
/*****************************************************************************
 FUNCTION	: UnpackTextureFixedPoint

 PURPOSE	: Unpack the result of a texture sample to C10 or U8 and store it
			  into the destination of an input instruciton.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psInputInst		- Input instruction.
			  psSampleResultLayout
								- Format of the texture sample result.
			  psSampleResult	- Location of the intermediate registers
								containing the texture sample result.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32 uU8Mask, uOneMask, uZeroMask;	
	IMG_UINT32 uChan;

	uU8Mask = uOneMask = uZeroMask = 0;
	for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
	{
		USC_CHANNELFORM	eFormat = psSampleResultLayout->asChannelLocation[uChan].eFormat;

		if (eFormat == USC_CHANNELFORM_U8)
		{
			uU8Mask |= (1U << uChan);
		}
		if (eFormat == USC_CHANNELFORM_ONE)
		{
			uOneMask |= (1U << uChan);
		}
		if (eFormat == USC_CHANNELFORM_ZERO)
		{
			uZeroMask |= (1U << uChan);
		}
	}

	/* Check for the special case of 8-bit texture data. */
	if ((uU8Mask | uOneMask | uZeroMask) == USC_DESTMASK_FULL)
	{
		UnpackU8Texture(psState,
						psCodeBlock,
						psInputInst,
						psSampleResultLayout,
						psSampleResult);
	}
	else
	{	
		UnpackTextureC10(psState,
						 psCodeBlock,
						 psSampleResultLayout,
						 psSampleResult,
						 psInputInst);
	}
}

static
PCODEBLOCK ConvertSamplerInstructionC10USCHW(PINTERMEDIATE_STATE psState,
									 		 PCODEBLOCK psCodeBlock,
									  		 PUNIFLEX_INST psSrc,
									  		 IMG_BOOL bConditional)
/*****************************************************************************
 FUNCTION	: ConvertSamplerInstructionC10USCHW

 PURPOSE	: Convert an input LD/LDL/LDB/LDD/LDP instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.
			  bConditional		- Whether the instruction is conditionally executed.

 RETURNS	: None.
*****************************************************************************/
{
	SAMPLE_RESULT_LAYOUT sSampleResultLayout;
	SAMPLE_RESULT sSampleResult;
	
	/* Get the raw results of the texture load in a register. */
	psCodeBlock = ConvertSamplerInstructionCore(psState, 
												psCodeBlock, 
												psSrc, 
												&sSampleResultLayout, 
												&sSampleResult, 
												bConditional);	

	/* Unpack the texture load result to U8 or C10. */
	UnpackTextureFixedPoint(psState, psCodeBlock, psSrc, &sSampleResultLayout, &sSampleResult);

	/* Do destination modifiers. */
	ApplyDestModC10(psState, psCodeBlock, psSrc);

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}

	/* Free memory allocated by ConvertSamplerInstructionCore. */
	FreeSampleResultLayout(psState, &sSampleResultLayout);

	return psCodeBlock;
}

static IMG_VOID ConvertLoadTiledInstructionC10(PINTERMEDIATE_STATE	psState, 
											   PCODEBLOCK			psCodeBlock, 
											   PUNIFLEX_INST		psInputInst)
/*****************************************************************************
 FUNCTION	: ConvertLoadTiledInstructionC10
    
 PURPOSE	: Convert an input load tiled instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psInputInst		- Instruction to convert.
			  
 RETURNS	: None.
*****************************************************************************/
{
	SAMPLE_RESULT_LAYOUT	sSampleResultLayout;
	SAMPLE_RESULT			sSampleResult;
	ARG						asSrc[2];
	IMG_UINT32				uSrc;

	/*
		Convert the base and stride sources to the intermediate format.
	*/
	for (uSrc = 0; uSrc < 2; uSrc++)
	{
		GetSourceF32(psState,
					 psCodeBlock,
					 &psInputInst->asSrc[uSrc],
					 USC_X_CHAN,
					 &asSrc[uSrc],
					 IMG_FALSE /* bAllowSourceMod */,
					 NULL /* psSourceMod */);
		ASSERT(psInputInst->asSrc[uSrc].byMod == 0);
	}

	/* Get the raw results of the texture load in a register. */
 	ConvertLoadTiledInstructionCore(psState, 
									psCodeBlock, 
									psInputInst, 
									&asSrc[0], 
									&asSrc[1], 
									&sSampleResultLayout, 
									&sSampleResult);
	
	/* Unpack the result to 32 bits. */
	UnpackTextureFixedPoint(psState, 
							psCodeBlock, 
							psInputInst,
							&sSampleResultLayout,
							&sSampleResult);

	/*
		Free details of the result of the texture sample.
	*/
	FreeSampleResultLayout(psState, &sSampleResultLayout);
}
#endif /* defined(OUTPUT_USCHW) */

#if defined(OUTPUT_USPBIN)
static
PCODEBLOCK ConvertSamplerInstructionC10USPBIN(PINTERMEDIATE_STATE	psState, 
											  PCODEBLOCK			psCodeBlock, 
											  PUNIFLEX_INST			psSrc, 
											  IMG_BOOL				bConditional)
/*****************************************************************************
 FUNCTION	: ConvertSamplerInstructionC10USPBIN

 PURPOSE	: Convert an input LD/LDL/LDB/LDD/LDP instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.
			  bConditional		- Whether the instruction is conditionally executed.

 RETURNS	: None.
*****************************************************************************/
{	
	IMG_UINT32		uChanMask;
	IMG_UINT32		uChanSwizzle;
	ARG				sDest;
	IMG_BOOL		bTempDest;
	UF_REGFORMAT	eDestFormat;
	IMG_UINT32		uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32		uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;

	uChanMask		= ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);
	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if (psState->psTargetFeatures->ui32Flags2 & SGX_FEATURE_FLAGS2_USE_C10U8_CHAN_ORDER_RGBA)
	{
		uChanSwizzle	= psSrc->asSrc[1].u.uSwiz;
	}
	else
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	{
		uChanSwizzle	= (psSrc->asSrc[1].u.uSwiz & ~((0x7U << 0) | (0x7U << 6))) |
						  ((psSrc->asSrc[1].u.uSwiz & (0x7U << 0)) << 6) |
						  ((psSrc->asSrc[1].u.uSwiz & (0x7U << 6)) >> 6);
	}

	bTempDest = IMG_FALSE;
	/*
		The patcher texture sample instruction can't have a predicate so go
		to a temporary destination if the input texture sample is predicated.
	*/
	if ((psSrc->uPredicate & UF_PRED_COMP_MASK) != UF_PRED_NONE)
	{
		bTempDest = IMG_TRUE;
	}

	eDestFormat = GetRegisterFormat(psState, &psSrc->sDest);
	/*
		Do the conversion to C10/U8 format in a seperate instruction rather than
		doing it directly in the patcher texture sample instruction. This gives
		a better chance of optimising the conversion away.
	*/
	if (
			eDestFormat == UF_REGFORMAT_C10 &&
			GetRegisterFormat(psState, &psSrc->asSrc[1]) == UF_REGFORMAT_C10	
	   )
	{
		eDestFormat = UF_REGFORMAT_U8;
		bTempDest = IMG_TRUE;
	}
	else if (
			eDestFormat == UF_REGFORMAT_U8 &&
			GetRegisterFormat(psState, &psSrc->asSrc[1]) == UF_REGFORMAT_U8	
	   )
	{
		eDestFormat = UF_REGFORMAT_U8;
		bTempDest = IMG_TRUE;
	}

	/* Setup the location where we want the data to be sampled */
	if	(bTempDest)
	{
		InitInstArg(&sDest);
		sDest.uType			= USEASM_REGTYPE_TEMP;
		sDest.uNumber		= GetNextRegister(psState);
		sDest.eFmt			= eDestFormat;
	}
	else
	{
		GetDestinationC10(psState, &psSrc->sDest, &sDest);
	}

	/* Get the raw results of the texture load in a register. */
	psCodeBlock = ConvertSamplerInstructionCoreUSP(psState,
								  psCodeBlock,
								  psSrc,
								  uChanMask,
								  uChanSwizzle,
								  &sDest,
								  bConditional);

	/* Do destination modifiers. */
	if (uSat != UFREG_DMOD_SATNONE || uScale != UFREG_DMOD_SCALEMUL1)
	{
		GenerateDestModC10(psState, psCodeBlock, &sDest, uSat, uScale, psSrc->sDest.u.byMask);
	}

	/*
		Conditionally write the sampled (and unpacked) data to the final destination
	*/
	if	(bTempDest)
	{
		if ((psSrc->uPredicate & UF_PRED_COMP_MASK) == UF_PRED_XYZW)
		{
			IMG_UINT32	uChan;
			IMG_UINT32	uOpcode;

			if	(sDest.eFmt == UF_REGFORMAT_U8)
			{
				uOpcode	= IPCKU8U8;
			}
			else
			{
				uOpcode	= IPCKC10C10;
			}
	
			/*
				The predicate is potentially different for every channel so do a seperate
				pack instruction for each channel.
			*/
			for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
			{
				if (uChanMask & (1U << uChan))
				{
					PINST psInst;

					/*
						Perform a predicated write of this component only
					*/
					psInst = AllocateInst(psState, IMG_NULL);
					SetOpcode(psState, psInst, uOpcode);
					psInst->u.psPck->bScale = IMG_TRUE;
					psInst->auDestMask[0] = 1 << uChan;
					GetInputPredicateInst(psState, psInst, psSrc->uPredicate, uChan);
					GetDestinationC10(psState, &psSrc->sDest, &psInst->asDest[0]); 
					psInst->asArg[0].uType = sDest.uType;
					psInst->asArg[0].uNumber = sDest.uNumber;
					psInst->asArg[0].eFmt = sDest.eFmt;
					SetPCKComponent(psState, psInst, 0 /* uArgIdx */, uChan);
					psInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
					psInst->asArg[1].uNumber = 0;
					AppendInst(psState, psCodeBlock, psInst);
				}
			}
		}
		else
		{
			PINST	psSopWmInst;

			psSopWmInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psSopWmInst, ISOPWM);
			psSopWmInst->auDestMask[0] = uChanMask;
			GetInputPredicateInst(psState, psSopWmInst, psSrc->uPredicate, 0);
			GetDestinationC10(psState, &psSrc->sDest, &psSopWmInst->asDest[0]);
			psSopWmInst->asArg[0].uType = sDest.uType;
			psSopWmInst->asArg[0].uNumber = sDest.uNumber;
			psSopWmInst->asArg[0].eFmt = sDest.eFmt;
			psSopWmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psSopWmInst->asArg[1].uNumber = 0;
			psSopWmInst->asArg[1].eFmt = UF_REGFORMAT_U8;
			/*
				RESULT = (1 - ZERO) * SRC1 + ZERO * SRC2
			*/
			psSopWmInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
			psSopWmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
			psSopWmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			psSopWmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
			psSopWmInst->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
			psSopWmInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
			AppendInst(psState, psCodeBlock, psSopWmInst);
		}
	}

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}
	return psCodeBlock;
}
#endif	/* #if defined(OUTPUT_USPBIN) */

#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
static IMG_VOID ConvertReformatInstructionF16F32ToC10_Vec(PINTERMEDIATE_STATE	psState, 
														  PCODEBLOCK			psCodeBlock, 
														  PUNIFLEX_INST			psInputInst)
/*****************************************************************************
 FUNCTION	: ConvertReformatInstructionF16F32ToC10_Vec

 PURPOSE	: Convert an input instruction which does a conversion from F16 or F32
			  to U8 or C10 to an intermediate instruction.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psInputSrc		- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
{
	PINST			psPckInst;
	PUF_REGISTER	psSrcArg = &psInputInst->asSrc[0];
	UF_REGFORMAT	eSrcFormat = psSrcArg->eFormat;
	IMG_UINT32		uUsedChanMask = GetSourceLiveChans(psState, psInputInst, 0 /* uSrc */);

	psPckInst = AllocateInst(psState, NULL);

	/*
		Set the instruction opcode.
	*/
	if (psInputInst->sDest.eFormat == UF_REGFORMAT_C10)
	{
		SetOpcode(psState, psPckInst, IVPCKC10FLT);
	}
	else
	{
		ASSERT(psInputInst->sDest.eFormat == UF_REGFORMAT_U8);

		SetOpcode(psState, psPckInst, IVPCKU8FLT);
	}
	psPckInst->u.psVec->bPackScale = IMG_TRUE;

	/*
		Convert the input destination 
	*/
	GetDestinationC10(psState, &psInputInst->sDest, &psPckInst->asDest[0]);

	/*
		Convert the destination mask.
	*/
	psPckInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psInputInst->sDest.u.byMask);

	/*
		Convert the source register to the intermediate format.
	*/
	if (eSrcFormat == UF_REGFORMAT_F16)
	{
		GetSourceF16_Vec(psState,
						 psCodeBlock,
						 psSrcArg,
						 uUsedChanMask,
						 psPckInst,
						 0 /* uSrcIdx */);
	}
	else
	{
		GetSourceF32_Vec(psState,
						 psCodeBlock,
						 psSrcArg,
						 uUsedChanMask,
						 psPckInst,
						 0 /* uSrcIdx */);
	}

	/*
		Convert the source swizzle. C10 and U8 use BGRA channel order so we need to apply an
		extra swizzle.
	*/
	psPckInst->u.psVec->auSwizzle[0] = ConvertSwizzle(psState, psSrcArg->u.uSwiz);
	psPckInst->u.psVec->auSwizzle[0] = 
		CombineSwizzles(psPckInst->u.psVec->auSwizzle[0], ConvertSwizzle(psState, GetInputToU8C10IntermediateSwizzle(psState)));

	/*
		Add the instruction to the end of the current block.
	*/
	AppendInst(psState, psCodeBlock, psPckInst);
}
#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */


static IMG_VOID ConvertMoveInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertMoveInstructionC10

 PURPOSE	: Convert an input MOV instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
{
	UF_REGFORMAT eSrcFmt = GetRegisterFormat(psState, &psSrc->asSrc[0]);
	IMG_UINT32 uSwizMask = MaskToSwiz(psSrc->sDest.u.byMask);
	IMG_UINT32 uSwizzledMask = SwizzleMask(psSrc->asSrc[0].u.uSwiz, psSrc->sDest.u.byMask);
	IMG_UINT32 uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32 uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	IMG_UINT32 uPredType = psSrc->uPredicate & UF_PRED_COMP_MASK;

	if (psSrc->sDest.u.byMask == 0)
	{
		return;
	}

	if (
			(eSrcFmt == UF_REGFORMAT_C10 || eSrcFmt == UF_REGFORMAT_U8) && 
			(psSrc->asSrc[0].u.uSwiz & uSwizMask) == (UFREG_SWIZ_NONE & uSwizMask) &&
			CanOverrideSwiz(&psSrc->asSrc[0]) &&
			!g_abSingleBitSet[psSrc->sDest.u.byMask] &&
			uPredType != UF_PRED_XYZW
	   )
	{
		if (psSrc->sDest.u.byMask == USC_DESTMASK_FULL &&
			psSrc->sDest.eFormat == eSrcFmt)
		{
			PINST	psMoveInst;
			ARG		sArg0  = USC_ARG_DEFAULT_VALUE;

			psMoveInst = AllocateInst(psState, IMG_NULL);
			
			GetSourceC10(psState, psCodeBlock, &psSrc->asSrc[0], psSrc->asSrc[0].byMod, &sArg0, 
				psSrc->sDest.u.byMask, IMG_TRUE, IMG_FALSE, psSrc->asSrc[0].eFormat);

			if(psSrc->sDest.eFormat == UF_REGFORMAT_U8 && sArg0.eFmt == UF_REGFORMAT_C10)
			{
				ConvertC10ArgToU8(psState, psCodeBlock, &sArg0, &sArg0, USC_DESTMASK_FULL);
			}

			SetOpcode(psState, psMoveInst, IMOV);
			
			if (uPredType != UF_PRED_NONE)
			{
				GetInputPredicateInst(psState, psMoveInst, psSrc->uPredicate, 0);
			}
			GetDestinationC10(psState, &psSrc->sDest, &psMoveInst->asDest[0]);
			psMoveInst->asArg[0] = sArg0;
			AppendInst(psState, psCodeBlock, psMoveInst);

			/* Do destination modifiers. */
			GenerateDestModC10(psState, psCodeBlock, &psMoveInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);
		}
		else
		{
			PINST		psSopWmInst;

			psSopWmInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psSopWmInst, ISOPWM);

			if (uPredType != UF_PRED_NONE)
			{
				GetInputPredicateInst(psState, psSopWmInst, psSrc->uPredicate, 0);
			}

			GetDestinationC10(psState, &psSrc->sDest, &psSopWmInst->asDest[0]);
			psSopWmInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);

			GetSourceC10(psState, 
						 psCodeBlock, 
						 &psSrc->asSrc[0],
						 psSrc->asSrc[0].byMod, 
						 &psSopWmInst->asArg[0], 
						 uSwizzledMask, 
						 IMG_TRUE, 
						 IMG_TRUE, 
						 psSrc->asSrc[0].eFormat);

			psSopWmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psSopWmInst->asArg[1].uNumber = 0;
			psSopWmInst->asArg[1].eFmt = UF_REGFORMAT_U8;

			psSopWmInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
			psSopWmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
			psSopWmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
			psSopWmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
			psSopWmInst->u.psSopWm->uCop = psSopWmInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
	
			AppendInst(psState, psCodeBlock, psSopWmInst);

			/* Do destination modifiers. */
			GenerateDestModC10(psState, psCodeBlock, &psSopWmInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);
		}
	}
	else if ((psSrc->sDest.eFormat == UF_REGFORMAT_U8 && eSrcFmt == UF_REGFORMAT_C10) ||
			 (psSrc->sDest.eFormat == UF_REGFORMAT_C10 && eSrcFmt == UF_REGFORMAT_U8))
	{
		PINST		psSopWmInst;

		if (uPredType != UF_PRED_XYZW)
		{
			psSopWmInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psSopWmInst, ISOPWM);
			GetDestinationC10(psState, &psSrc->sDest, &psSopWmInst->asDest[0]);
			psSopWmInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);
			GetSourceC10(psState, 
						 psCodeBlock, 
						 &psSrc->asSrc[0], 
						 psSrc->asSrc[0].byMod, 
						 &psSopWmInst->asArg[0], 
						 psSrc->sDest.u.byMask, 
						 IMG_FALSE, 
						 IMG_TRUE, 
						 psSrc->asSrc[0].eFormat);
			psSopWmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
			psSopWmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
		
			psSopWmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psSopWmInst->asArg[1].uNumber = 0;
			psSopWmInst->asArg[1].eFmt = UF_REGFORMAT_U8;

			psSopWmInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
			psSopWmInst->u.psSopWm->uCop = psSopWmInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
			psSopWmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
			AppendInst(psState, psCodeBlock, psSopWmInst);

			/* Do destination modifiers. */
			GenerateDestModC10(psState, psCodeBlock, &psSopWmInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);
		}
		else
		{
			ARG			sC10Src;
			PINST		psPackInst = NULL;
			IMG_UINT32	uChan;
			IMG_BOOL	bIgnoreSwiz;
			IMG_UINT32	uSwiz;

			if (CanOverrideSwiz(&psSrc->asSrc[0]))
			{
				bIgnoreSwiz = IMG_TRUE;
				uSwiz = psSrc->asSrc[0].u.uSwiz;
			}
			else
			{
				bIgnoreSwiz = IMG_FALSE;
				uSwiz = UFREG_SWIZ_NONE;
				uSwizzledMask = psSrc->sDest.u.byMask;
			}

			GetSourceC10(psState, psCodeBlock, &psSrc->asSrc[0], psSrc->asSrc[0].byMod, &sC10Src, uSwizzledMask, 
				bIgnoreSwiz, IMG_FALSE, psSrc->asSrc[0].eFormat);

			for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
			{
				IMG_UINT32	uSrcChan = EXTRACT_CHAN(uSwiz, uChan);
				IMG_UINT32	uConvertTemp = GetNextRegister(psState);

				if ((psSrc->sDest.u.byMask & (1U << uChan)) == 0)
				{
					continue;
				}

				psPackInst = AllocateInst(psState, IMG_NULL);
				if (sC10Src.eFmt == UF_REGFORMAT_U8)
				{
					SetOpcode(psState, psPackInst, IUNPCKF32U8);
				}
				else
				{
					SetOpcode(psState, psPackInst, IUNPCKF32C10);
				}
				psPackInst->u.psPck->bScale = IMG_TRUE;
				psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
				psPackInst->asDest[0].uNumber = uConvertTemp;
				psPackInst->asArg[0] = sC10Src;
				SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uSrcChan));
				AppendInst(psState, psCodeBlock, psPackInst);

				psPackInst = AllocateInst(psState, IMG_NULL);
				if (psSrc->sDest.eFormat == UF_REGFORMAT_U8)
				{
					SetOpcode(psState, psPackInst, IPCKU8F32);
				}
				else
				{
					SetOpcode(psState, psPackInst, IPCKC10F32);
				}
				psPackInst->u.psPck->bScale = IMG_TRUE;
				GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
				psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
				psPackInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
				psPackInst->asArg[0].uNumber = uConvertTemp;
				AppendInst(psState, psCodeBlock, psPackInst);
			}

			/* Do destination modifiers. */
			GenerateDestModC10(psState, psCodeBlock, &psPackInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);
		}
	}
	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	else if (
				(
					eSrcFmt == UF_REGFORMAT_F16 ||
					eSrcFmt == UF_REGFORMAT_F32
				) &&
				(psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_VEC34) != 0
			)
	{
		 ConvertReformatInstructionF16F32ToC10_Vec(psState, psCodeBlock, psSrc);
	}
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	else
	{
		IMG_UINT32	uChan;
		ARG			sC10Src = USC_ARG_DEFAULT_VALUE;
		PINST		psPackInst;
		IMG_BOOL	bOverlappingChannels;
		IMG_BOOL	bIgnoreSwiz;
		IMG_UINT32	uSwiz;
		ARG			sDest;
		IMG_UINT32	uTempDest;

		if (CanOverrideSwiz(&psSrc->asSrc[0]))
		{
			bIgnoreSwiz = IMG_TRUE;
			uSwiz = psSrc->asSrc[0].u.uSwiz;
		}
		else
		{
			bIgnoreSwiz = IMG_FALSE;
			uSwiz = UFREG_SWIZ_NONE;
			uSwizzledMask = psSrc->sDest.u.byMask;
		}

		if (eSrcFmt == UF_REGFORMAT_C10 || eSrcFmt == UF_REGFORMAT_U8)
		{
				GetSourceC10(psState, psCodeBlock, &psSrc->asSrc[0], psSrc->asSrc[0].byMod, &sC10Src, uSwizzledMask, 
					bIgnoreSwiz, IMG_FALSE, psSrc->asSrc[0].eFormat);
		}

		/*
			Check if any channels from the source are used after being written. Since we are breaking the
			move into per-channel writes we need to use a temporary destination in that case.
		*/
		bOverlappingChannels = IMG_FALSE;
		if (psSrc->sDest.eType == psSrc->asSrc[0].eType &&
			psSrc->sDest.uNum == psSrc->asSrc[0].uNum)
		{
			if (eSrcFmt != GetRegisterFormat(psState, &psSrc->sDest))
			{
				bOverlappingChannels = IMG_TRUE;
			}
			else
			{
				for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
				{
					IMG_UINT32	uPrevChan;

					if ((psSrc->sDest.u.byMask & (1U << uChan)) == 0)
					{
						continue;
					}
	
					for (uPrevChan = 0; uPrevChan < uChan; uPrevChan++)
					{
						if (EXTRACT_CHAN(psSrc->asSrc[0].u.uSwiz, uPrevChan) == uChan)
						{
							bOverlappingChannels = IMG_TRUE;
							break;
						}
					}

					if (bOverlappingChannels)
					{
						break;
					}
				}
			}
		}

		/*
			Get the destination register in the intermediate format.
		*/
		GetDestinationC10(psState, &psSrc->sDest, &sDest);

		/*
			Get a temporary register for the result of the move.
		*/
		uTempDest = USC_UNDEF;
		if (bOverlappingChannels)
		{
			uTempDest = GetNextRegister(psState);
		}

		/*
			Generate a move for each channel.
		*/
		for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
		{
			IMG_UINT32	uSrcChan = EXTRACT_CHAN(uSwiz, uChan);

			if ((psSrc->sDest.u.byMask & (1U << uChan)) == 0)
			{
				continue;
			}

			if (uSrcChan >= UFREG_SWIZ_1 && uSrcChan <= UFREG_SWIZ_2)
			{
				psPackInst = BaseConvertF32ImmediateToC10(psState, psSrc->sDest.eFormat, uSrcChan);
			}
			else
			{
				psPackInst = AllocateInst(psState, IMG_NULL);

				switch (eSrcFmt)
				{
					case UF_REGFORMAT_U8: 
					{
						ASSERT(psSrc->sDest.eFormat == UF_REGFORMAT_U8);
						if(sC10Src.eFmt == UF_REGFORMAT_C10)
						{
							/* Conversion to U8 format is required. */
							ConvertC10ArgToU8(psState, psCodeBlock, &sC10Src, &sC10Src, uSwizzledMask);
							SetOpcode(psState, psPackInst, IPCKU8U8); 
						}
						else if(sC10Src.eFmt == UF_REGFORMAT_U8)
						{
							SetOpcode(psState, psPackInst, IPCKU8U8);
						}
						psPackInst->asArg[0] = sC10Src;
						SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uSrcChan));
						break;
					}
					case UF_REGFORMAT_C10: 
					{
						ASSERT(psSrc->sDest.eFormat == UF_REGFORMAT_C10);
						SetOpcode(psState, psPackInst, IPCKC10C10); 
						psPackInst->asArg[0] = sC10Src;
						SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uSrcChan));
						break;
					}
					case UF_REGFORMAT_F16: 
					{
						FLOAT_SOURCE_MODIFIER	sMod;
						IMG_UINT32				uComponent;

						SetOpcode(psState, psPackInst,	
								  (psSrc->sDest.eFormat == UF_REGFORMAT_C10) ? IPCKC10F16 : IPCKU8F16); 
						psPackInst->u.psPck->bScale = IMG_TRUE;
						GetSingleSourceF16(psState, 
										   psCodeBlock, 
										   &psSrc->asSrc[0], 
										   &psPackInst->asArg[0], 
										   &uComponent,
										   uChan, 
										   IMG_TRUE, 
										   &sMod,
										   IMG_FALSE);
						ApplyFloatSourceModifier(psState, 
												 psCodeBlock, 
												 NULL /* psInsertBeforeInst */,
												 &psPackInst->asArg[0], 
												 &psPackInst->asArg[0], 
												 UF_REGFORMAT_F16,
												 &sMod);
						SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, uComponent);
						break;
					}
					case UF_REGFORMAT_F32: 
					{
						ARG			sU8HWConst = USC_ARG_DEFAULT_VALUE;
						IMG_BOOL	bSrcIsAU8HWConst = IMG_FALSE;

						/* Try to fetch as a U8 hardware constant. */
						if(psSrc->sDest.eFormat == UF_REGFORMAT_U8 && 
						psSrc->asSrc[0].eType == UFREG_TYPE_CONST)
						{
							IMG_UINT32 uSwizL = bIgnoreSwiz ? UFREG_SWIZ_NONE : psSrc->asSrc[0].u.uSwiz;
							InitInstArg(&sU8HWConst);
							if(GetC10OrU8StaticConstant(psState, &psSrc->asSrc[0], uSwizzledMask, uSwizL, IMG_FALSE, &sU8HWConst))
							{
								bSrcIsAU8HWConst = IMG_TRUE;
							}
						}

						if(bSrcIsAU8HWConst && sU8HWConst.eFmt == UF_REGFORMAT_U8)
						{
							SetOpcode(psState, psPackInst, IPCKU8U8);
							psPackInst->asArg[0] = sU8HWConst;
							SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uSrcChan));
						}
						else
						{
							FLOAT_SOURCE_MODIFIER	sMod;

							SetOpcode(psState, psPackInst,	
								  (psSrc->sDest.eFormat == UF_REGFORMAT_C10) ? IPCKC10F32 : IPCKU8F32);  
							psPackInst->u.psPck->bScale = IMG_TRUE;
							GetSourceF32(psState, 
										 psCodeBlock, 
										 &psSrc->asSrc[0], 
										 uChan, 
										 &psPackInst->asArg[0], 
										 IMG_TRUE,
										 &sMod);
							ApplyFloatSourceModifier(psState, 
													 psCodeBlock, 
													 NULL /* psInsertBeforeInst */,
													 &psPackInst->asArg[0], 
													 &psPackInst->asArg[0], 
													 UF_REGFORMAT_F32,
													 &sMod);
						}
						break;
					}
					default: imgabort();
				}
			}
			psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psPackInst->asArg[1].uNumber = 0;

			psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
			if (bOverlappingChannels)
			{
				psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
				psPackInst->asDest[0].uNumber = uTempDest;
				psPackInst->asDest[0].eFmt = psSrc->sDest.eFormat;
			}
			else
			{
				psPackInst->asDest[0] = sDest;
				if (uPredType != UF_PRED_NONE)
				{
					GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);
				}
			}

			AppendInst(psState, psCodeBlock, psPackInst);
		}

		if (bOverlappingChannels)
		{
			/*
				If the move has per-channel predicates then do the move from the
				temporary destination into the real destination with seperate
				instructions for each channel.
			*/
			if (uPredType == UF_PRED_XYZW && !g_abSingleBitSet[psSrc->sDest.u.byMask])
			{
				for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
				{
					PINST	psMoveInst;

					if ((psSrc->sDest.u.byMask & (1U << uChan)) == 0)
					{
						continue;
					}

					psMoveInst = AllocateInst(psState, IMG_NULL);
					SetOpcode(psState, psMoveInst, IPCKC10C10);
					psMoveInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
					GetDestinationC10(psState, &psSrc->sDest, &psMoveInst->asDest[0]);
					GetInputPredicateInst(psState, psMoveInst, psSrc->uPredicate, uChan);
					psMoveInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
					psMoveInst->asArg[0].uNumber = uTempDest;
					SetPCKComponent(psState, psMoveInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uChan));
					psMoveInst->asArg[0].eFmt = psSrc->sDest.eFormat;
					psMoveInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
					psMoveInst->asArg[1].uNumber = 0;
					AppendInst(psState, psCodeBlock, psMoveInst);
				}
			}
			else
			{
				PINST		psMoveInst;
				IMG_UINT32	uPredChan;

				for (uPredChan = 0; (psSrc->sDest.u.byMask & (1U << uPredChan)) == 0; uPredChan++);

				psMoveInst = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psMoveInst, ISOPWM);
				psMoveInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, psSrc->sDest.u.byMask);
				GetDestinationC10(psState, &psSrc->sDest, &psMoveInst->asDest[0]);
				if (uPredType != UF_PRED_NONE)
				{
					GetInputPredicateInst(psState, psMoveInst, psSrc->uPredicate, uPredChan);
				}
				psMoveInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
				psMoveInst->asArg[0].uNumber = uTempDest;
				psMoveInst->asArg[0].eFmt = psSrc->sDest.eFormat;
				psMoveInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psMoveInst->asArg[1].uNumber = 0;
				psMoveInst->u.psSopWm->uSel1 = USEASM_INTSRCSEL_ZERO;
				psMoveInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
				psMoveInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
				psMoveInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
				psMoveInst->u.psSopWm->uCop = USEASM_INTSRCSEL_ADD;
				psMoveInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
				AppendInst(psState, psCodeBlock, psMoveInst);
			}
		}
		
		if (psSrc->sDest.u.byMask != 0)
		{
			/* Do destination modifiers. */
			GenerateDestModC10(psState, psCodeBlock, &sDest, uSat, uScale, psSrc->sDest.u.byMask);
		}
	}

	/* Store into an indexable temporary register. */
	if (psSrc->sDest.eType == UFREG_TYPE_INDEXABLETEMP)
	{
		StoreIndexableTemp(psState, psCodeBlock, &psSrc->sDest, UF_REGFORMAT_C10, USC_TEMPREG_C10INDEXTEMPDEST);
	}
	else if (psSrc->sDest.eType == UFREG_TYPE_VSOUTPUT)
	{
		ConvertDestinationC10(psState, psCodeBlock, psSrc, &psSrc->sDest);
	}
}

#if defined(SUPPORT_SGX545)
/*****************************************************************************
 FUNCTION	: ConvertSincosC10HWSupport

 PURPOSE	: Convert an sincos instruction to the intermediate format where the
			  target processor directly supports sin and cos instruction..

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
static IMG_VOID ConvertSincosC10HWSupport(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
{
	IMG_UINT32	uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32	uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	IMG_UINT32	uChan;
	ARG			sArg = USC_ARG_DEFAULT_VALUE;
	IMG_UINT32	uSourceChan;
	IMG_UINT32	uDestMask = psSrc->sDest.u.byMask & 3;
	IMG_BOOL	bIgnoreSwiz;
	PINST		psUnpackInst;
	PINST		psMulInst;
	IMG_UINT32	uTempDestStart = GetNextRegisterCount(psState, 2 /* uCount */);

	if (CanOverrideSwiz(&psSrc->asSrc[0]))
	{
		bIgnoreSwiz = IMG_TRUE;
		uSourceChan = EXTRACT_CHAN(psSrc->asSrc[0].u.uSwiz, UFREG_SWIZ_A);
	}
	else
	{
		bIgnoreSwiz = IMG_FALSE;
		uSourceChan = UFREG_SWIZ_B;
	}

	GetSourceC10(psState, psCodeBlock, &psSrc->asSrc[0], psSrc->asSrc[0].byMod, &sArg, 1 << uSourceChan, bIgnoreSwiz, 
		IMG_FALSE, psSrc->asSrc[0].eFormat);

	/*
		Unpack the C10 result to F32.
	*/
	psUnpackInst = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psUnpackInst, IUNPCKF32C10);
	psUnpackInst->u.psPck->bScale = IMG_TRUE;
	psUnpackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psUnpackInst->asDest[0].uNumber = USC_TEMPREG_TEMPSRC;
	psUnpackInst->asArg[0] = sArg;
	SetPCKComponent(psState, psUnpackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uSourceChan));
	AppendInst(psState, psCodeBlock, psUnpackInst);

	/*
		TEMP = SRC * (2/PI)
	*/
	psMulInst = AllocateInst(psState, IMG_NULL);
	SetOpcode(psState, psMulInst, IFMUL);
	psMulInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psMulInst->asDest[0].uNumber = USC_TEMPREG_TEMPSRC;
	psMulInst->asArg[0] = psUnpackInst->asDest[0];
	psMulInst->asArg[1].uType = USEASM_REGTYPE_FPCONSTANT;
	psMulInst->asArg[1].uNumber = EURASIA_USE_SPECIAL_CONSTANT_FLOAT2OVERPI;
	AppendInst(psState, psCodeBlock, psMulInst);

	for (uChan = 0; uChan < 2; uChan++)
	{
		PINST	psInst;

		if (!(uDestMask & (1U << uChan)))
		{
			continue;
		}

		psInst = AllocateInst(psState, IMG_NULL);

		SetOpcode(psState, psInst, (uChan == 0) ? IFCOS : IFSIN);

		psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psInst->asDest[0].uNumber = uTempDestStart + uChan;
		psInst->asArg[0] = psMulInst->asDest[0];

		AppendInst(psState, psCodeBlock, psInst);
	}

	/* Move from the temporaries into the destination. */
	for (uChan = 0; uChan < 2; uChan++)
	{
		PINST	psPackInst;

		if (!(uDestMask & (1U << uChan)))
		{
			continue;
		}

		psPackInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psPackInst, IPCKC10F32);
		psPackInst->u.psPck->bScale = IMG_TRUE;
		psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
		GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
		GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, 0);
		psPackInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
		psPackInst->asArg[0].uNumber = uTempDestStart + uChan;
		psPackInst->asArg[0].eFmt = UF_REGFORMAT_F32;
		psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
		psPackInst->asArg[1].uNumber = 0;
		AppendInst(psState, psCodeBlock, psPackInst);

		if ((uDestMask >> (uChan + 1)) == 0)
		{
			/* Do any destination modifiers. */
			GenerateDestModC10(psState, psCodeBlock, &psPackInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);
		}
	}
}

/*****************************************************************************
 FUNCTION	: ConvertSincos2C10HWSupport

 PURPOSE	: Convert an sincos instruction to the intermediate format where the
			  target processor directly supports sin and cos instruction..

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
static IMG_VOID ConvertSincos2C10HWSupport(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
{
	IMG_UINT32	uSat = (psSrc->sDest.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32	uScale = (psSrc->sDest.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	IMG_UINT32	uSat2 = (psSrc->sDest2.byMod & UFREG_DMOD_SAT_MASK) >> UFREG_DMOD_SAT_SHIFT;
	IMG_UINT32	uScale2 = (psSrc->sDest2.byMod & UFREG_DMOD_SCALE_MASK) >> UFREG_DMOD_SCALE_SHIFT;
	IMG_UINT32	uChan;
	ARG			sArg = USC_ARG_DEFAULT_VALUE;
	IMG_UINT32	uSourceChan;
	IMG_UINT32	uDestMask = psSrc->sDest.u.byMask & USC_DESTMASK_FULL;
	IMG_UINT32	uDest2Mask = psSrc->sDest2.u.byMask & USC_DESTMASK_FULL;
	IMG_BOOL	bIgnoreSwiz;
	PINST		psUnpackInst;
	PINST		psMulInst;

	for(uChan=0; uChan<CHANNELS_PER_INPUT_REGISTER; uChan++)
	{	
		if (CanOverrideSwiz(&psSrc->asSrc[0]))
		{
			bIgnoreSwiz = IMG_TRUE;
			uSourceChan = EXTRACT_CHAN(psSrc->asSrc[0].u.uSwiz, uChan);
		}
		else
		{
			bIgnoreSwiz = IMG_FALSE;
			uSourceChan = uChan;
		}

		GetSourceC10(psState, psCodeBlock, &psSrc->asSrc[0], psSrc->asSrc[0].byMod, &sArg, 1 << uSourceChan, bIgnoreSwiz, 
			IMG_FALSE, psSrc->asSrc[0].eFormat);

		/*
			Unpack the C10/U8 result to F32.
		*/
		psUnpackInst = AllocateInst(psState, IMG_NULL);
		if(sArg.eFmt == UF_REGFORMAT_U8)
		{
			SetOpcode(psState, psUnpackInst, IUNPCKF32U8);
		}
		else
		{
			SetOpcode(psState, psUnpackInst, IUNPCKF32C10);
		}
		psUnpackInst->u.psPck->bScale = IMG_TRUE;
		psUnpackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psUnpackInst->asDest[0].uNumber = USC_TEMPREG_TEMPSRC;
		psUnpackInst->asArg[0] = sArg;
		SetPCKComponent(psState, psUnpackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uSourceChan));
		AppendInst(psState, psCodeBlock, psUnpackInst);

		/*
			TEMP = SRC * (2/PI)
		*/
		psMulInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psMulInst, IFMUL);
		psMulInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psMulInst->asDest[0].uNumber = USC_TEMPREG_TEMPSRC;
		psMulInst->asArg[0] = psUnpackInst->asDest[0];
		psMulInst->asArg[1].uType = USEASM_REGTYPE_FPCONSTANT;
		psMulInst->asArg[1].uNumber = EURASIA_USE_SPECIAL_CONSTANT_FLOAT2OVERPI;
		AppendInst(psState, psCodeBlock, psMulInst);

		if ((uDestMask & (1U << uChan)))
		{
			PINST		psInst;
			PINST		psPackInst;
			IMG_UINT32	uSinDest = GetNextRegister(psState);

			psInst = AllocateInst(psState, IMG_NULL);

			SetOpcode(psState, psInst, IFSIN);

			psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psInst->asDest[0].uNumber = uSinDest;
			psInst->asArg[0] = psMulInst->asDest[0];

			AppendInst(psState, psCodeBlock, psInst);

			/* Move from the temporaries into the destination. */		
			psPackInst = AllocateInst(psState, IMG_NULL);
			if(psSrc->sDest.eFormat == UF_REGFORMAT_U8)
			{
				SetOpcode(psState, psPackInst, IPCKU8F32);
			}
			else
			{
				SetOpcode(psState, psPackInst, IPCKC10F32);
			}
			psPackInst->u.psPck->bScale = IMG_TRUE;
			psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
			GetDestinationC10(psState, &psSrc->sDest, &psPackInst->asDest[0]);
			GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, 0);
			psPackInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
			psPackInst->asArg[0].uNumber = uSinDest;
			psPackInst->asArg[0].eFmt = UF_REGFORMAT_F32;
			psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psPackInst->asArg[1].uNumber = 0;
			AppendInst(psState, psCodeBlock, psPackInst);

			if ((uDestMask >> (uChan + 1)) == 0)
			{
				/* Do any destination modifiers. */
				GenerateDestModC10(psState, psCodeBlock, &psPackInst->asDest[0], uSat, uScale, psSrc->sDest.u.byMask);
			}
		}

		if ((uDest2Mask & (1U << uChan)))
		{
			PINST		psInst;
			PINST		psPackInst;
			IMG_UINT32	uCosDest = GetNextRegister(psState);

			psInst = AllocateInst(psState, IMG_NULL);

			SetOpcode(psState, psInst, IFCOS);

			psInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psInst->asDest[0].uNumber = uCosDest;
			psInst->asArg[0] = psMulInst->asDest[0];

			AppendInst(psState, psCodeBlock, psInst);
		
			/* Move from the temporaries into the destination. */		
			psPackInst = AllocateInst(psState, IMG_NULL);
			if(psSrc->sDest2.eFormat == UF_REGFORMAT_U8)
			{
				SetOpcode(psState, psPackInst, IPCKU8F32);
			}
			else
			{
				SetOpcode(psState, psPackInst, IPCKC10F32);
			}
			psPackInst->u.psPck->bScale = IMG_TRUE;
			psPackInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, 1 << uChan);
			GetDestinationC10(psState, &psSrc->sDest2, &psPackInst->asDest[0]);
			GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, 0);
			psPackInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
			psPackInst->asArg[0].uNumber = uCosDest;
			psPackInst->asArg[0].eFmt = UF_REGFORMAT_F32;
			psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psPackInst->asArg[1].uNumber = 0;
			AppendInst(psState, psCodeBlock, psPackInst);

			if ((uDest2Mask >> (uChan + 1)) == 0)
			{
				/* Do any destination modifiers. */
				GenerateDestModC10(psState, psCodeBlock, &psPackInst->asDest[0], uSat2, uScale2, psSrc->sDest2.u.byMask);
			}
		}
	}
}
#endif /* defined(SUPPORT_SGX545) */

IMG_INTERNAL
IMG_VOID CreateComparisonC10(PINTERMEDIATE_STATE psState,
						     PCODEBLOCK psCodeBlock,
							 IMG_UINT32 uPredDest,
							 UFREG_COMPOP uCompOp,
							 IMG_UINT32 uChanOp,
							 PARG psSrc1,
							 PARG psSrc2,
							 IMG_UINT32 uChan,
						     IMG_UINT32 uCompPredSrc,
							 IMG_BOOL bCompPredNegate,
							 IMG_BOOL bInvert)
/*****************************************************************************
 FUNCTION	: CreateComparisonC10

 PURPOSE	: Generate instructions to do a comparison between two registers and 
			  put the result in USE register p0.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  uCompOp			- Comparison type.
			  psSrc1			- First source to be compared.
			  psSrc2			- Second source to be compared.
			  dwChan			- Channel within the sources to be compared.

 RETURNS	: None.
*****************************************************************************/
{
	PINST psInst;
	ARG sTempSrc1 = USC_ARG_DEFAULT_VALUE;
	ARG sTempSrc2;
	IMG_UINT32 uChanSel;

	if (bInvert)
	{
		uCompOp = g_puInvertCompOp[uCompOp];
	}

	/*
		Fix BRN 21784 by doing the test calculation in a seperate instruction.
	*/
	if ((psState->psTargetBugs->ui32Flags & SGX_BUG_FLAGS_FIX_HW_BRN_21784) != 0 &&
		!(psSrc1->uType == USEASM_REGTYPE_IMMEDIATE &&
		  psSrc1->uNumber == 0))
	{
		if (psSrc2->uType == USEASM_REGTYPE_IMMEDIATE &&
			psSrc2->uNumber == 0)
		{
			sTempSrc1 = *psSrc2;
			sTempSrc2 = *psSrc1;

			psSrc1 = &sTempSrc1;
			psSrc2 = &sTempSrc2;
		}
		else
		{
			PINST		psSopInst;
	
			psSopInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psSopInst, ISOPWM);
			psSopInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psSopInst->asDest[0].uNumber = GetNextRegister(psState);
			psSopInst->asDest[0].eFmt = UF_REGFORMAT_C10;
			psSopInst->asArg[0] = *psSrc1;
			psSopInst->asArg[1] = *psSrc2;

			psSopInst->u.psSopWm->uCop = USEASM_INTSRCSEL_SUB;
			psSopInst->u.psSopWm->uAop = psSopInst->u.psSopWm->uCop;
			psSopInst->u.psSopWm->bComplementSel1 = psSopInst->u.psSopWm->bComplementSel2 = IMG_TRUE;
			psSopInst->u.psSopWm->uSel1 = psSopInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;

			AppendInst(psState, psCodeBlock, psSopInst);

			/*
				Make the TEST sources 0 and the result of the SOPWM.
			*/
			InitInstArg(&sTempSrc1);
			sTempSrc1.uType = USEASM_REGTYPE_IMMEDIATE;
			sTempSrc1.uNumber = 0;
			psSrc1 = &sTempSrc1;

			sTempSrc2 = psSopInst->asDest[0];
			psSrc2 = &sTempSrc2;

			uCompOp = g_puNegateCompOp[uCompOp];
		}
	}

	/*
		Set up the TEST instruction.
	*/
	psInst = AllocateInst(psState, IMG_NULL);
	SetOpcodeAndDestCount(psState, psInst, ITESTPRED, TEST_PREDICATE_ONLY_DEST_COUNT);
	psInst->u.psTest->eAluOpcode = IFPSUB8;
	SetPredicate(psState, psInst, uCompPredSrc, bCompPredNegate);
	MakePredicateArgument(&psInst->asDest[TEST_PREDICATE_DESTIDX], uPredDest);
	
	psInst->asArg[0] = *psSrc1;
	psInst->asArg[1] = *psSrc2;

	CompOpToTest(psState, uCompOp, &psInst->u.psTest->sTest);

	/*
		Check the ANDALL/ORALL options.
	*/
	if (uChanOp)
	{
		if (uChanOp == UFREG_COMPCHANOP_ANDALL)
		{
			uChanSel = USEASM_TEST_CHANSEL_ANDALL;
		}
		else
		{
			ASSERT(uChanOp == UFREG_COMPCHANOP_ORALL);
			uChanSel = USEASM_TEST_CHANSEL_ORALL;
		}
	}
	else
	{
		uChanSel = ConvertInputChannelToIntermediate(psState, uChan);
	}
	psInst->u.psTest->sTest.eChanSel = uChanSel;

	/*
		If a TEST instruction uses the alpha channel of a C10 source then
		the source must be a temporary register.
	*/
	if (uChanSel == USEASM_TEST_CHANSEL_C3 ||
		uChanSel == USEASM_TEST_CHANSEL_ANDALL ||
		uChanSel == USEASM_TEST_CHANSEL_ORALL)
	{
		IMG_UINT32	uArg;

		for (uArg = 0; uArg < 2; uArg++)
		{
			PARG	psArg = &psInst->asArg[uArg];

			if (psArg->uType != USEASM_REGTYPE_TEMP &&
				TypeUsesFormatControl(psArg->uType) &&
				psArg->eFmt == UF_REGFORMAT_C10)
			{
				PINST	psMovInst;

				psMovInst = AllocateInst(psState, IMG_NULL);
				SetOpcode(psState, psMovInst, IMOV);
				psMovInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
				psMovInst->asDest[0].uNumber = GetNextRegister(psState);
				psMovInst->asDest[0].eFmt = UF_REGFORMAT_C10;
				psMovInst->asArg[0] = *psArg;
				AppendInst(psState, psCodeBlock, psMovInst);

				*psArg = psMovInst->asDest[0];
			}
		}
	}

	/*
		Check the restrictions on the sources to FPADD8/FPSUB8.
	*/
	if (!CanUseSrc(psState, psInst, 1 /* uArgIdx */, psInst->asArg[1].uType, psInst->asArg[1].uIndexType))
	{
		if (
				(psState->psTargetBugs->ui32Flags & SGX_BUG_FLAGS_FIX_HW_BRN_21784) == 0 &&
				(
					psInst->u.psTest->eAluOpcode == IFPADD8 ||
					(
						psInst->u.psTest->eAluOpcode == IFPSUB8 &&
						psInst->asArg[1].uType == USEASM_REGTYPE_IMMEDIATE &&
						psInst->asArg[1].uNumber == 0
					 )
				 ) && 
				CanUseSrc(psState, psInst, 1 /* uArgIdx */, psInst->asArg[0].uType, psInst->asArg[0].uIndexType)
			)
		{
			ARG	sTemp;

			if (psInst->u.psTest->eAluOpcode == IFPSUB8)
			{
				psInst->u.psTest->eAluOpcode = IFPADD8;
			}

			sTemp = psInst->asArg[1];
			psInst->asArg[1] = psInst->asArg[0];
			psInst->asArg[0] = sTemp;
		}
		else
		{
			PINST	psMoveInst;

			psMoveInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psMoveInst, IMOV);
			psMoveInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			psMoveInst->asDest[0].uNumber = USC_TEMPREG_TEMPSRC + 1;
			psMoveInst->asDest[0].eFmt = psInst->asArg[1].eFmt;
			psMoveInst->asArg[0] = psInst->asArg[1];
			AppendInst(psState, psCodeBlock, psMoveInst);

			psInst->asArg[1] = psMoveInst->asDest[0];
		}
	}

	AppendInst(psState, psCodeBlock, psInst);
}

static IMG_VOID ConvertSetpInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc)
/*****************************************************************************
 FUNCTION	: ConvertSetpInstructionC10

 PURPOSE	: Convert an input SETP instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32 uChan;
	IMG_UINT32 uCompOp;
	ARG sSrc1, sSrc2;
	IMG_UINT32 uCompChannel = UINT_MAX;
	IMG_UINT32 uUsedChans;
	IMG_UINT32 uChanOp;

	uCompOp = psSrc->asSrc[1].uNum & (~UFREG_COMPCHANOP_MASK);
	uChanOp = ((psSrc->asSrc[1].uNum & UFREG_COMPCHANOP_MASK) >>  UFREG_COMPCHANOP_SHIFT);

	/*
		Check if we could generate better code by using another channel and avoiding
		a swizzle.
	*/
	if	(
			g_abSingleBitSet[psSrc->sDest.u.byMask] && 
			((psSrc->uPredicate & UF_PRED_COMP_MASK) == UF_PRED_NONE)
		)
	{
		IMG_UINT32	uSrc0Chan;
		IMG_UINT32	uSrc2Chan;

		for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
		{
			if (psSrc->sDest.u.byMask & (1U << uChan))
			{
				uCompChannel = uChan;
				break;
			}
		}

		uSrc0Chan = EXTRACT_CHAN(psSrc->asSrc[0].u.uSwiz, uCompChannel);
		uSrc2Chan = EXTRACT_CHAN(psSrc->asSrc[2].u.uSwiz, uCompChannel);

		if (uSrc0Chan == uSrc2Chan &&
			uSrc0Chan <= UFREG_SWIZ_A &&
			EXTRACT_CHAN(psSrc->asSrc[0].u.uSwiz, uSrc0Chan) == uSrc0Chan &&
			EXTRACT_CHAN(psSrc->asSrc[2].u.uSwiz, uSrc0Chan) == uSrc0Chan)
		{
			uCompChannel = uSrc0Chan;
		}

		uUsedChans = 1 << uCompChannel;
	}
	else
	{
		uUsedChans = psSrc->sDest.u.byMask;
		if(!g_abSingleBitSet[psSrc->sDest.u.byMask])
		{
			/* Ignore the channel options */
			uChanOp = UFREG_COMPCHANOP_NONE;
		}
	}

	/* Set all channels to be used for ANDALL/ORALL*/
	if(uChanOp)
	{
		uUsedChans = USC_DESTMASK_FULL;
	}

	/* Get the source registers. */
	GetSourceC10(psState, psCodeBlock, &psSrc->asSrc[0], psSrc->asSrc[0].byMod, &sSrc1, uUsedChans, IMG_FALSE, 
		IMG_TRUE, psSrc->asSrc[0].eFormat);
	GetSourceC10(psState, psCodeBlock, &psSrc->asSrc[2], psSrc->asSrc[2].byMod, &sSrc2, uUsedChans, IMG_FALSE, 
		IMG_TRUE, psSrc->asSrc[2].eFormat);

	for (uChan = 0; uChan < 4; uChan++)
	{
		IMG_UINT32	uPredDest;
		IMG_UINT32	uPredSrc;
		IMG_BOOL	bPredNegate;

		/* Ignore this component if it isn't included in the instruction mask. */
		if ((psSrc->sDest.u.byMask & (1U << uChan)) == 0)
		{
			continue;
		}

		/* 
			Create the instruction to do the comparison.
		*/
		ASSERT(psSrc->sDest.uNum < psState->uInputPredicateRegisterCount);
		uPredDest = USC_PREDREG_P0X + (psSrc->sDest.uNum * CHANNELS_PER_INPUT_REGISTER) + uChan;

		GetInputPredicate(psState, &uPredSrc, &bPredNegate, psSrc->uPredicate, uChan);

		if(uChanOp)
		{
			CreateComparisonC10(psState,
								psCodeBlock,
								uPredDest,
								(UFREG_COMPOP)uCompOp,
								uChanOp,
								&sSrc1,
								&sSrc2,
								uCompChannel == UINT_MAX ? uChan : uCompChannel,
								uPredSrc,
								bPredNegate,
								IMG_FALSE);
			uChan = (IMG_UINT32)4;
		}
		else
		{
			CreateComparisonC10(psState,
								psCodeBlock,
								uPredDest,
								(UFREG_COMPOP)uCompOp,
								(IMG_UINT32)0,
								&sSrc1,
								&sSrc2,
								uCompChannel == UINT_MAX ? uChan : uCompChannel,
								uPredSrc,
								bPredNegate,
								IMG_FALSE);
		}
	}
}

static IMG_VOID KillOneChannel(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PARG psSrc, IMG_UINT32 uTestChan, IMG_BOOL bConditional, UF_OPCODE eType)
/*****************************************************************************
 FUNCTION	: KillOneChannel

 PURPOSE	: Do a single texkill test.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Source for the texkill.
			  uTestChan			- Channel to test.
			  bConditional		- TRUE if the instruction is inside a conditional
								block.

 RETURNS	: None.
*****************************************************************************/
{
	PINST psInst;

	psInst = AllocateInst(psState, IMG_NULL);
	SetOpcodeAndDestCount(psState, psInst, ITESTPRED, TEST_PREDICATE_ONLY_DEST_COUNT);
	psInst->u.psTest->eAluOpcode = IFPADD8;
	/*
		Do we need to combine this texkill result with a previous one?
	*/
	if (bConditional || (psState->uFlags & USC_FLAGS_TEXKILL_PRESENT) != 0)
	{
		SetPredicate(psState, psInst, USC_PREDREG_TEXKILL, IMG_FALSE /* bPredNegate */);
	}

	/*
		Initialise the texkill result at the start of the program if
		the first write is conditional.
	*/
	if ((psState->uFlags & USC_FLAGS_TEXKILL_PRESENT) == 0)
	{
		if (bConditional)
		{
			psState->uFlags |= USC_FLAGS_INITIALISE_TEXKILL;
		}
		else
		{
			psState->uFlags &= ~USC_FLAGS_INITIALISE_TEXKILL;
		}
	}
	psState->uFlags |= USC_FLAGS_TEXKILL_PRESENT;
	MakePredicateArgument(&psInst->asDest[TEST_PREDICATE_DESTIDX], USC_PREDREG_TEXKILL);
	if (eType == UFOP_KPLE)
	{
		/* SRC > 0 */
		CompOpToTest(psState, UFREG_COMPOP_GT, &psInst->u.psTest->sTest);
	}
	else
	{
		/* SRC >= 0 */
		CompOpToTest(psState, UFREG_COMPOP_GE, &psInst->u.psTest->sTest);
	}
	psInst->u.psTest->sTest.eChanSel = uTestChan;

	psInst->asArg[0].uType = USEASM_REGTYPE_IMMEDIATE;
	psInst->asArg[0].uNumber = 0;
	psInst->asArg[1] = *psSrc;

	AppendInst(psState, psCodeBlock, psInst);
}

static IMG_VOID ConvertTexkillInstructionC10(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PUNIFLEX_INST psSrc, IMG_BOOL bConditional)
/*****************************************************************************
 FUNCTION	: ConvertTexkillInstructionC10

 PURPOSE	: Convert an input KPLT/KPLE instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.
			  bConditional		- TRUE if the texkill is inside a conditional block.

 RETURNS	: None.
*****************************************************************************/
{
	IMG_UINT32	uChan;
	ARG			sSrc;
	IMG_UINT32	uSwiz;
	IMG_UINT32	uSrcMask;

	/*
		Can we do the swizzle directly in the instruction?
	*/
	if (CanOverrideSwiz(&psSrc->asSrc[0]))
	{
		uSwiz = psSrc->asSrc[0].u.uSwiz;
		uSrcMask = SwizzleMask(uSwiz, USC_DESTMASK_FULL);
	}
	else
	{
		uSwiz = UFREG_SWIZ_NONE;
		uSrcMask = USC_DESTMASK_FULL;
	}

	/*
		Get the texkill source.
	*/
	GetSourceC10(psState, psCodeBlock, &psSrc->asSrc[0], psSrc->asSrc[0].byMod, &sSrc, uSrcMask, IMG_TRUE,
		IMG_TRUE, psSrc->asSrc[0].eFormat);

	if (uSwiz == UFREG_SWIZ_NONE)
	{
		KillOneChannel(psState, psCodeBlock, &sSrc, USEASM_TEST_CHANSEL_ANDALL, bConditional, psSrc->eOpCode);
	}
	else
	{
		for (uChan = 0; uChan < CHANNELS_PER_INPUT_REGISTER; uChan++)
		{
			IMG_UINT32	uPrevChan;
			IMG_UINT32	uSrcChan = EXTRACT_CHAN(uSwiz, uChan);
			IMG_BOOL	bDupChan;

			/*
				Check if this channel is a duplicate of a previous one.
			*/
			bDupChan = IMG_FALSE;
			for (uPrevChan = 0; uPrevChan < uChan; uPrevChan++)
			{
				if (EXTRACT_CHAN(uSwiz, uPrevChan) == uSrcChan)
				{
					bDupChan = IMG_TRUE;
					break;
				}
			}
			if (bDupChan)
			{
				continue;
			}

			KillOneChannel(psState, 
						   psCodeBlock, 
						   &sSrc, 
						   ConvertInputChannelToIntermediate(psState, uSrcChan), 
						   bConditional, 
						   psSrc->eOpCode);
		}
	}
}

#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
static
IMG_VOID GetGradientsC10_Vec(PINTERMEDIATE_STATE	psState,
							 PCODEBLOCK				psCodeBlock,
							 IMG_UINT32				uGradDim,
							 IMG_UINT32				uCoord,	
							 PSAMPLE_GRADIENTS		psGradients,
							 PARG					psC10Grad)	
/*****************************************************************************
 FUNCTION	: GetGradientsC10_Vec
    
 PURPOSE	: Extract gradients for a texture sample instruction on cores
			  which support the vector instruction set.

 PARAMETERS	: psState 		- Compiler state.
			  psCodeBlock	- Block for any extra instructions.
			  psInputInst	- Texture load instruction.
			  uGradDim		- Dimensions of the texture being sampled.
			  uCoord		- Coordinate to get gradients for.
			  eGradFormat	- Format of the gradients expected by the
							texture sample instruction.
			  psC10Grad		- Intermediate argument containing the gradient
							data.

 OUTPUT		: None.
			  
 RETURNS	: None.
*****************************************************************************/
{
	PINST		psPackInst;
	IMG_UINT32	uConvertTemp;

	/*
		Get a temporary register for the data converted from C10 format.
	*/
	uConvertTemp = GetNextRegister(psState);

	/*
		Convert the data from C10 format to the format the intermediate
		texture sample uses for gradients.
	*/
	psPackInst = AllocateInst(psState, NULL);
	if (psC10Grad->eFmt == UF_REGFORMAT_C10)
	{
		SetOpcode(psState, psPackInst, IVPCKFLTC10);
		psPackInst->u.psVec->aeSrcFmt[0] = UF_REGFORMAT_C10;
	}
	else
	{
		ASSERT(psC10Grad->eFmt == UF_REGFORMAT_U8);
		SetOpcode(psState, psPackInst, IVPCKFLTU8);
		psPackInst->u.psVec->aeSrcFmt[0] = UF_REGFORMAT_U8;
	}

	psPackInst->u.psVec->bPackScale = IMG_TRUE;

	psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
	psPackInst->asDest[0].uNumber = uConvertTemp;
	psPackInst->asDest[0].eFmt = psGradients->eGradFormat;

	psPackInst->asArg[0] = *psC10Grad;
	psPackInst->u.psVec->auSwizzle[0] = GetInputToU8C10IntermediateSwizzle(psState); 

	AppendInst(psState, psCodeBlock, psPackInst);

	/*
		Generate instructions to swizzle/move the gradient data into the correct
		arrangement.
	*/
	UnpackGradients_Vec(psState,
						psCodeBlock,
						NULL,
						uConvertTemp,
						uGradDim,
						uCoord,
						psGradients->eGradFormat,
						psGradients);
}
#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */

IMG_INTERNAL 
IMG_VOID GetGradientsC10(PINTERMEDIATE_STATE	psState,
						 PCODEBLOCK				psCodeBlock,
						 PUNIFLEX_INST			psInputSrc,
						 IMG_UINT32				uGradDim,
						 IMG_UINT32				uCoord,
						 PSAMPLE_GRADIENTS		psGradients)
/*****************************************************************************
 FUNCTION	: GetGradientsC10
    
 PURPOSE	: Extract gradients for a texture sample instruction

 PARAMETERS	: psState 		- Compiler state.
			  psCodeBlock	- Block for any extra instructions.
			  psInputInst	- Texture load instruction.
			  uGradMask		- Mask of gradients to get.
			  uCoord		- Coordinate to get gradients for.

 OUTPUT		: None.
			  
 RETURNS	: None.
*****************************************************************************/
{
	/* Get the gradients for this access. */
	if (uGradDim > 0)
	{
		ARG			sGrad;
		IMG_UINT32	uChan;

		GetSourceC10(psState, 
					 psCodeBlock, 
					 &psInputSrc->asSrc[2 + uCoord], 
					 psInputSrc->asSrc[2 + uCoord].byMod, 
					 &sGrad, 
					 (1U << uGradDim) - 1, 
					 IMG_FALSE, 
					 IMG_FALSE,
					 psInputSrc->asSrc[2 + uCoord].eFormat);

		/*
			Unpack to floating point - the hardware only accepts gradients in this
			format.
		*/
		#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
		if (psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_VEC34)
		{
			GetGradientsC10_Vec(psState, 
								psCodeBlock,
								uGradDim,
								uCoord,
								psGradients,
								&sGrad);
		}
		else
		#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
		{
			for (uChan = 0; uChan < uGradDim; uChan++)
			{
				PINST		psPackInst;
				IMG_UINT32	uDestOffset = uChan * 2 + uCoord;

				psPackInst = AllocateInst(psState, IMG_NULL);
				if (psGradients->eGradFormat == UF_REGFORMAT_F32)
				{
					if (sGrad.eFmt == UF_REGFORMAT_U8)
					{
						SetOpcode(psState, psPackInst, IUNPCKF32U8);
					}
					else
					{
						SetOpcode(psState, psPackInst, IUNPCKF32C10);
					}
				}
				else
				{
					if (sGrad.eFmt == UF_REGFORMAT_U8)
					{
						SetOpcode(psState, psPackInst, IUNPCKF16U8);
					}
					else	
					{
						SetOpcode(psState, psPackInst, IUNPCKF16C10);
					}

					psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
					psPackInst->asArg[1].uNumber = 0;
				}
				psPackInst->u.psPck->bScale = IMG_TRUE;
				psPackInst->auDestMask[0] = USC_DESTMASK_FULL;
				psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
				psPackInst->asDest[0].uNumber = psGradients->uGradStart + uDestOffset;
				psPackInst->asDest[0].eFmt = psGradients->eGradFormat;
				psPackInst->asArg[0] = sGrad;
				SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uChan));
				AppendInst(psState, psCodeBlock, psPackInst);
			}
		}
	}
}

IMG_INTERNAL
IMG_VOID GetSampleIdxC10(PINTERMEDIATE_STATE	psState,
						 PCODEBLOCK				psCodeBlock,
						 PUNIFLEX_INST			psInputInst,
						 PARG					psSampleIdx)
/*****************************************************************************
 FUNCTION	: GetSampleIdxC10
    
 PURPOSE	: Extract sample idx for a texture sample instruction

 PARAMETERS	: psState 		- Compiler state.
			  psCodeBlock	- Block for any extra instructions.
			  psInputInst	- Texture load instruction.
			  psSampleIdx	- Sample Idx. update related info.

 OUTPUT		: None.
			  
 RETURNS	: None.
*****************************************************************************/
{		
	ARG sGrad;	
	GetSourceC10(
					psState, 
					psCodeBlock, 
					&psInputInst->asSrc[2], 
					psInputInst->asSrc[2].byMod, 
					&sGrad, 
					1,
					IMG_FALSE, 
					IMG_FALSE,
					psInputInst->asSrc[2].eFormat);
	
	{
		PINST		psPackInst;
		psPackInst = AllocateInst(psState, IMG_NULL);		
		if (sGrad.eFmt == UF_REGFORMAT_U8)
		{
			SetOpcode(psState, psPackInst, IUNPCKF32U8);
		}
		else
		{
			SetOpcode(psState, psPackInst, IUNPCKF32C10);
		}		
		psPackInst->u.psPck->bScale = IMG_TRUE;
		psPackInst->asDest[0] = *psSampleIdx;
		psPackInst->auDestMask[0] = USC_DESTMASK_FULL;		
		psPackInst->asArg[0] = sGrad;
		SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, 0));
		AppendInst(psState, psCodeBlock, psPackInst);
	}
}

static
IMG_VOID ConvertDataFromC10(PINTERMEDIATE_STATE		psState,
						    PCODEBLOCK				psBlock,
							IMG_UINT32				uOutTempStart,
							UF_REGFORMAT			eOutFormat,
							PARG					psInArg,
							IMG_UINT32				uInSwizzle,
							IMG_UINT32				uConvertChanCount)
/*****************************************************************************
 FUNCTION	: ConvertDataFromC10
    
 PURPOSE	: Convert data from C10 or U8 format to F16 to F32.

 PARAMETERS	: psState 		- Compiler state.
			  psCodeBlock	- Block for any extra instructions.
			  uOutTempStart	- Start of the temporaries to write with the
							converted data.
			  eOutFormat	- Format to convert to.
			  psInArg		- Data to be converted.
			  uInSwizzle	- Swizzle to be applied when converting.
			  uConvertChanCount
							- Count of C10/U8 channels to convert.

 OUTPUT		: None.
			  
 RETURNS	: None.
*****************************************************************************/
{
	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if ((psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_VEC34) != 0)
	{
		PINST	psUnpackInst;

		psUnpackInst = AllocateInst(psState, IMG_NULL);

		if (psInArg->eFmt == UF_REGFORMAT_C10)
		{
			SetOpcode(psState, psUnpackInst, IVPCKFLTC10);
		}
		else
		{
			ASSERT(psInArg->eFmt == UF_REGFORMAT_U8);
			SetOpcode(psState, psUnpackInst, IVPCKFLTU8);
		}
		psUnpackInst->u.psVec->bPackScale = IMG_TRUE;
	
		psUnpackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psUnpackInst->asDest[0].uNumber = uOutTempStart;
		psUnpackInst->asDest[0].eFmt = eOutFormat; 
		psUnpackInst->auDestMask[0] = (1U << uConvertChanCount) - 1;
	
		psUnpackInst->asArg[0] = *psInArg;
		psUnpackInst->u.psVec->auSwizzle[0] = ConvertSwizzle(psState, uInSwizzle);
		psUnpackInst->u.psVec->aeSrcFmt[0] = psInArg->eFmt;
		
		AppendInst(psState, psBlock, psUnpackInst);
	}
	else
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	{
		IMG_UINT32	uChan;

		for (uChan = 0; uChan < uConvertChanCount; uChan++)
		{
			PINST	psUnpackInst;

			psUnpackInst = AllocateInst(psState, IMG_NULL);

			if (eOutFormat == UF_REGFORMAT_F32)
			{
				if (psInArg->eFmt == UF_REGFORMAT_U8)
				{
					SetOpcode(psState, psUnpackInst, IUNPCKF32U8);
				}
				else
				{
					ASSERT(psInArg->eFmt == UF_REGFORMAT_C10);
					SetOpcode(psState, psUnpackInst, IUNPCKF32C10);
				}
				
			}
			else
			{
				ASSERT(eOutFormat == UF_REGFORMAT_F16);
				if (psInArg->eFmt == UF_REGFORMAT_U8)
				{
					SetOpcode(psState, psUnpackInst, IUNPCKF16U8);
				}
				else
				{
					ASSERT(psInArg->eFmt == UF_REGFORMAT_C10);
					SetOpcode(psState, psUnpackInst, IUNPCKF16C10);
				}

				psUnpackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
				psUnpackInst->asArg[1].uNumber = 0;
			}
			psUnpackInst->u.psPck->bScale = IMG_TRUE;

			psUnpackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
			if (eOutFormat == UF_REGFORMAT_F32)
			{
				psUnpackInst->asDest[0].uNumber = uOutTempStart + uChan;
			}
			else
			{
				psUnpackInst->asDest[0].uNumber = uOutTempStart + uChan / 2;
				if ((uChan % 2) == 0)
				{
					psUnpackInst->auDestMask[0] = USC_XY_CHAN_MASK;
				}
				else
				{
					psUnpackInst->auDestMask[0] = USC_ZW_CHAN_MASK;
				}
			}
			psUnpackInst->asDest[0].eFmt = eOutFormat; 

			psUnpackInst->asArg[0] = *psInArg;
			SetPCKComponent(psState, psUnpackInst, 0 /* uArgIdx */, EXTRACT_CHAN(uInSwizzle, uChan));


			AppendInst(psState, psBlock, psUnpackInst);
		}
	}
}

IMG_INTERNAL
IMG_VOID GetLODAdjustmentC10(PINTERMEDIATE_STATE	psState,
							 PCODEBLOCK				psCodeBlock,
							 PUNIFLEX_INST			psInputInst,
							 PSAMPLE_LOD_ADJUST		psLODAdjust)
/*****************************************************************************
 FUNCTION	: GetLODAdjustmentC10

 PURPOSE	: Generate instructions to put the LOD adjustment value in
			  a fixed register.

 PARAMETERS	: psState		- Compiler state
			  psCodeBlock	- Block for any extra instructions.
			  psInputInst	- Input instruction.
			  psLODAdjust	- Details of where the intermediate texture sample
							expects the LOD adjust parameter.

 RETURNS	: None.
*****************************************************************************/
{
	ARG				sArg0;
	PUF_REGISTER	psSrcArg;

	if(psInputInst->eOpCode != UFOP_LD2DMS)
	{
		psSrcArg = &psInputInst->asSrc[2];
	}
	else
	{
		psSrcArg = &psInputInst->asSrc[3];
	}
	/*
		Get the intermediate representation of the LOD bias/replace source
		to the input texture sample instruction.
	*/
	GetSourceC10(psState, 
				 psCodeBlock, 
				 psSrcArg, 
				 psSrcArg->byMod, 
				 &sArg0, 
				 USC_W_CHAN_MASK, 
				 IMG_FALSE, 
				 IMG_FALSE,
				 psSrcArg->eFormat);

	/*
		Unpack the C10 LOD adjustment to F32.
	*/
	ConvertDataFromC10(psState,
					   psCodeBlock,
					   psLODAdjust->uLODTemp,
					   psLODAdjust->eLODFormat,
					   &sArg0,
					   UFREG_SWIZ_WWWW,
					   1 /* uConvertChanCount */);
}

IMG_INTERNAL 
IMG_VOID GetSampleCoordinateArrayIndexC10(PINTERMEDIATE_STATE	psState, 
										  PCODEBLOCK			psCodeBlock, 
										  PUNIFLEX_INST			psInputSrc, 
										  IMG_UINT32			uSrcChan, 
										  IMG_UINT32			uTexture,
										  IMG_UINT32			uArrayIndexTemp)
/*****************************************************************************
 FUNCTION	: GetSampleCoordinateArrayIndexC10

 PURPOSE	: Convert the texture array index argument to a texture sample to 
			  the hardware format.

 PARAMETERS	: psState		- Compiler state
			  psCodeBlock	- Block for any extra instructions.
			  psInputSrc	- Texture coordinate source to the texture sample
							instruction.
			  uSrcChan		- Channel in the texture coordinate source which is the
							array index.
			  uTexture		- Index of the texture being sampled.
			  uArrayIndexTemp
							- Number of the variable to update with the
							texture array index.

 RETURNS	: None.
*****************************************************************************/
{	
	ARG			sC10Arg;
	IMG_UINT32	uConvertTemp = GetNextRegister(psState);

	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psInputSrc->asSrc[0], 
				 psInputSrc->asSrc[0].byMod, 
				 &sC10Arg, 
				 1 << uSrcChan, 
				 IMG_FALSE, 
				 IMG_FALSE, 
				 psInputSrc->asSrc[0].eFormat);

	#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
	if ((psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_VEC34) != 0)
	{
		PINST		psPackInst = AllocateInst(psState, IMG_NULL);

		/*
			Convert the U8/C10 array index to F32.
		*/
		if (sC10Arg.eFmt == UF_REGFORMAT_U8)
		{
			SetOpcode(psState, psPackInst, IVPCKFLTU8);
		}
		else
		{
			SetOpcode(psState, psPackInst, IVPCKFLTC10);
		}
		psPackInst->u.psVec->bPackScale = IMG_TRUE;
		psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psPackInst->asDest[0].uNumber = uConvertTemp;
		psPackInst->asDest[0].eFmt = UF_REGFORMAT_F32;
		psPackInst->asArg[0] = sC10Arg;
		psPackInst->u.psVec->auSwizzle[0] = 
			g_auReplicateSwizzles[ConvertInputChannelToIntermediate(psState, uSrcChan)];
		psPackInst->u.psVec->aeSrcFmt[0] = sC10Arg.eFmt;
		AppendInst(psState, psCodeBlock, psPackInst);

		/*
			Clamp the array index to the maximum element and convert it to U16.
		*/
		ConvertTextureArrayIndexToU16_Vec(psState, psCodeBlock, uTexture, uConvertTemp, UF_REGFORMAT_F32, uArrayIndexTemp);
	}
	else
	#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
	{
		PINST	psPackInst = AllocateInst(psState, IMG_NULL);
		ARG		sF32Arg;

		/*
			Convert the U8/C10 array index to F32.
		*/
		if (sC10Arg.eFmt == UF_REGFORMAT_U8)
		{
			SetOpcode(psState, psPackInst, IUNPCKF32U8);
		}
		else
		{
			SetOpcode(psState, psPackInst, IUNPCKF32C10);
		}
		psPackInst->u.psPck->bScale = IMG_TRUE;
		psPackInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psPackInst->asDest[0].uNumber = uConvertTemp;
		psPackInst->asDest[0].eFmt = UF_REGFORMAT_F32;
		psPackInst->asArg[0] = sC10Arg;
		SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, ConvertInputChannelToIntermediate(psState, uSrcChan));
		AppendInst(psState, psCodeBlock, psPackInst);

		InitInstArg(&sF32Arg);
		sF32Arg.uType = USEASM_REGTYPE_TEMP;
		sF32Arg.uNumber = uConvertTemp;

		/*
			Clamp the array index to the maximum element and convert it to U16.
		*/
		ConvertTextureArrayIndexToU16(psState, psCodeBlock, uTexture, &sF32Arg, 0 /* uFltComponent */, uArrayIndexTemp);
	}
}

IMG_INTERNAL
IMG_VOID GetProjectionC10(PINTERMEDIATE_STATE	psState,
						  PCODEBLOCK			psCodeBlock,
						  PUNIFLEX_INST			psInputInst,
						  PSAMPLE_PROJECTION	psProj,
						  UF_REGFORMAT			eCoordFormat)
/*****************************************************************************
 FUNCTION	: GetProjectionC10

 PURPOSE	: Extract the location of the value to project the texture coordinates
			  by from an input texture sample instruction.

 PARAMETERS	: psState		- Compiler state
			  psCodeBlock	- Block for any extra instructions.
			  psInputInst	- Input texture sample instruction.
			  psProj		- Returns details of the projection value.

 RETURNS	: None.
*****************************************************************************/
{
	PUF_REGISTER	psInputCoord = &psInputInst->asSrc[0];

	GetSourceC10(psState, 
				 psCodeBlock, 
				 psInputCoord, 
				 psInputCoord->byMod, 
				 &psProj->sProj, 
				 USC_W_CHAN_MASK, 
				 IMG_FALSE, 
				 IMG_FALSE, 
				 psInputCoord->eFormat);
	psProj->uProjChannel = USC_W_CHAN;
	psProj->uProjMask = USC_X_CHAN_MASK;
	    
	/* Sample coordinates can only be in C10 format. */
	if (psProj->sProj.eFmt == UF_REGFORMAT_U8)
	{
		ConvertU8ArgToC10(psState, psCodeBlock, &psProj->sProj, &psProj->sProj, USC_DESTMASK_FULL);
	}

	/*
		If the texture sample expects the coordinates in a higher precision format then insert instructions to
		convert.
	*/
	if (eCoordFormat != UF_REGFORMAT_C10 && eCoordFormat != UF_REGFORMAT_U8)
	{
		IMG_UINT32	uConvertTemp;

		uConvertTemp = GetNextRegister(psState);

		ConvertDataFromC10(psState,
						   psCodeBlock,
						   uConvertTemp,
						   eCoordFormat,
						   &psProj->sProj,
						   UFREG_SWIZ_WWWW,
						   1 /* uConvertChanCount */);

		InitInstArg(&psProj->sProj);
		psProj->sProj.uType = USEASM_REGTYPE_TEMP;
		psProj->sProj.uNumber = uConvertTemp;
		psProj->uProjChannel = USC_X_CHAN;
		psProj->uProjMask = USC_ALL_CHAN_MASK;
	}
}

IMG_INTERNAL 
IMG_VOID GetSampleCoordinatesC10(PINTERMEDIATE_STATE	psState,
								 PCODEBLOCK				psCodeBlock,
								 PUNIFLEX_INST			psInputInst,
								 IMG_UINT32				uDimensionality,
								 PSAMPLE_COORDINATES	psCoordinates,
								 IMG_BOOL				bPCF)
/*****************************************************************************
 FUNCTION	: GetSampleCoordinatesC10

 PURPOSE	: Get the intermediate representation of a C10 texture coordinate source.

 PARAMETERS	: psState		- Compiler state
			  psCodeBlock	- Block for any extra instructions.
			  psInputSrc	- Input texture sample instruction.
			  uDimensionality
							- Number of dimensions of the texture being
							sampled.
			  psCoordinates	- Details of the location and format of the
							texture coordinates.
			  bPCF			- TRUE if this is a sample using PCF.

 RETURNS	: None.
*****************************************************************************/
{
	PINST		psMoveInst;
	IMG_UINT32	uMaskFromSource0;
	ARG			sArg0;
	IMG_UINT32	uC10CoordTemp;

	if (psCoordinates->eCoordFormat != UF_REGFORMAT_C10)
	{
		uC10CoordTemp = GetNextRegister(psState);
	}
	else
	{
		uC10CoordTemp = psCoordinates->uCoordStart;
	}

	/*
		For the LDC/LDCLZ instruction the PCF comparison value comes from the third source.
	*/
	if (bPCF && (psInputInst->eOpCode == UFOP_LDC || psInputInst->eOpCode == UFOP_LDCLZ))
	{
		uMaskFromSource0 = (1U << (uDimensionality - 1)) - 1;
	}
	else
	{
		uMaskFromSource0 = (1U << uDimensionality) - 1;
	}

	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psInputInst->asSrc[0], 
				 psInputInst->asSrc[0].byMod, 
				 &sArg0, 
				 uMaskFromSource0, 
				 IMG_FALSE, 
				 IMG_FALSE, 
				 psInputInst->asSrc[0].eFormat);

	/* Sample coordinates can only be in C10 format. */
	if(sArg0.eFmt == UF_REGFORMAT_U8)
	{
		PINST psSopWmInst;
		psSopWmInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psSopWmInst, ISOPWM);
		psSopWmInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psSopWmInst->asDest[0].uNumber = uC10CoordTemp;
		psSopWmInst->asDest[0].eFmt = UF_REGFORMAT_C10;
		psSopWmInst->auDestMask[0] = USC_DESTMASK_FULL;
		psSopWmInst->asArg[0] = sArg0;
		psSopWmInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
		psSopWmInst->asArg[1].uNumber = 0;
		psSopWmInst->asArg[1].eFmt = UF_REGFORMAT_U8;
		psSopWmInst->u.psSopWm->uCop = psSopWmInst->u.psSopWm->uAop = USEASM_INTSRCSEL_ADD;
		psSopWmInst->u.psSopWm->uSel1 = psSopWmInst->u.psSopWm->uSel2 = USEASM_INTSRCSEL_ZERO;
		psSopWmInst->u.psSopWm->bComplementSel1 = IMG_TRUE;
		psSopWmInst->u.psSopWm->bComplementSel2 = IMG_FALSE;
		AppendInst(psState, psCodeBlock, psSopWmInst);
	}
	else
	{
		/* Get the coordinates for this access. */
		psMoveInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psMoveInst, IMOV);
		psMoveInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psMoveInst->asDest[0].uNumber = uC10CoordTemp;
		psMoveInst->asDest[0].eFmt = UF_REGFORMAT_C10;
		psMoveInst->asArg[0] = sArg0;
		AppendInst(psState, psCodeBlock, psMoveInst);
	}

	/*
		Move the PCF comparison value from the third source to the last channel
		of the texture coordinates.
	*/
	if (bPCF && (psInputInst->eOpCode == UFOP_LDC || psInputInst->eOpCode == UFOP_LDCLZ))
	{
		PINST	psPCKInst;

		psPCKInst = AllocateInst(psState, NULL);
		SetOpcode(psState, psPCKInst, IPCKC10C10);
		
		psPCKInst->asDest[0].uType = USEASM_REGTYPE_TEMP;
		psPCKInst->asDest[0].uNumber = uC10CoordTemp;
		psPCKInst->asDest[0].eFmt = UF_REGFORMAT_C10;
		psPCKInst->auDestMask[0] = ConvertInputWriteMaskToIntermediate(psState, (1U << (uDimensionality - 1)));
		GetSourceC10(psState,
					 psCodeBlock,
					 &psInputInst->asSrc[2],
					 psInputInst->asSrc[2].byMod,
					 &psPCKInst->asArg[0],
					 USC_W_CHAN_MASK,
					 IMG_FALSE,
					 IMG_FALSE,
					 psInputInst->asSrc[2].eFormat);
		SetPCKComponent(psState, psPCKInst, 0 /* uArgIdx */, USC_W_CHAN);
		psPCKInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
		psPCKInst->asArg[1].uNumber = 0;
		AppendInst(psState, psCodeBlock, psPCKInst);
	}

	/*
		If required up-convert the texture coordinates from C10 or U8.
	*/
	if (psCoordinates->eCoordFormat != UF_REGFORMAT_C10 && psCoordinates->eCoordFormat != UF_REGFORMAT_U8)
	{
		ARG	sConvertSource;

		ASSERT(psCoordinates->eCoordFormat == UF_REGFORMAT_F16 || psCoordinates->eCoordFormat == UF_REGFORMAT_F32);

		InitInstArg(&sConvertSource);
		sConvertSource.uType = USEASM_REGTYPE_TEMP;
		sConvertSource.eFmt = sArg0.eFmt;
		sConvertSource.uNumber = uC10CoordTemp;

		ConvertDataFromC10(psState,
						   psCodeBlock,
						   psCoordinates->uCoordStart,
						   psCoordinates->eCoordFormat,
						   &sConvertSource,
						   GetInputToU8C10IntermediateSwizzle(psState),
						   uDimensionality);
	}	
}

#if defined(SUPPORT_SGX531) || defined(SUPPORT_SGX540) || defined(SUPPORT_SGX541)
/*****************************************************************************
 FUNCTION	: ConvertNormaliseC10
    
 PURPOSE	: Convert a normalise instruction to the intermediate format.
`
 PARAMETERS	: psState		- Compiler state.
			  psCodeBlock	- Block to add the intermediate instructions to.
			  psSrc			- Instruction to convert.
              bVec4         - Whether a vec4 (true) or vec3 (false)
			  
 RETURNS	: None.
*****************************************************************************/
static 
IMG_VOID ConvertNormaliseC10(PINTERMEDIATE_STATE psState, 
							 PCODEBLOCK psCodeBlock, 
							 PUNIFLEX_INST psSrc,
							 IMG_BOOL bVec4)
{
	const IMG_UINT32 uNumChans = CHANNELS_PER_INPUT_REGISTER;
	const IMG_UINT32 uNumArgs = 2;
	const IMG_UINT32 uNumComps = bVec4 ? 4 : 3;	// Number of components that will be used.
	const IMG_UINT32 uChansPerDest = 2;
	PINST psPackInst;
	IMG_UINT32 uCtr;
	ARG sDestReg;
	ARG asArg[2];
	const IMG_UINT32 uTempDestNum = GetNextRegisterCount(psState, 2 /* uCount */);
	const IMG_UINT32 uTempSrcNum = GetNextRegisterCount(psState, 2 /* uCount */);
	ARG sC10Arg;
	const IMG_UINT32 uUsedChansMask = bVec4 ? 0xF : 0x7;
	IMG_BOOL bSrcModNegate;
	IMG_BOOL bSrcModAbsolute;
	IMG_BYTE bySrcMod;

	ASSERT(psState->psTargetFeatures->ui32Flags & 
		   SGX_FEATURE_FLAGS_USE_FNORMALISE);

	/* 
	   ufop_nrm dst, src
	   -->
	   fnrm dst, src.xy, src.yz, swizzle drc
	*/

	/* Set up the temporay destination and sources */
	InitInstArg(&sDestReg);

	sDestReg.uType = USEASM_REGTYPE_TEMP;
	sDestReg.uNumber = uTempDestNum;
	sDestReg.eFmt = UF_REGFORMAT_F16;

	for (uCtr = 0; uCtr < uNumArgs; uCtr ++)
	{
		InitInstArg(&asArg[uCtr]);

		asArg[uCtr].uType = USEASM_REGTYPE_TEMP;
		asArg[uCtr].uNumber = uTempSrcNum + uCtr;
		asArg[uCtr].eFmt = UF_REGFORMAT_F16;
	}

	/*
		Get the source modifiers.
	*/
	bSrcModNegate = IMG_FALSE;
	if (psSrc->asSrc[0].byMod & UFREG_SOURCE_NEGATE)
	{
		bSrcModNegate = IMG_TRUE;
	}
	bSrcModAbsolute = IMG_FALSE;
	if (psSrc->asSrc[0].byMod & UFREG_SOURCE_ABS)
	{
		bSrcModAbsolute = IMG_TRUE;
	}
	bySrcMod = (IMG_BYTE)(psSrc->asSrc[0].byMod & ~(UFREG_SOURCE_NEGATE | UFREG_SOURCE_ABS));

	/*
		Get the source in C10 format.
	*/
	GetSourceC10(psState, 
				 psCodeBlock, 
				 &psSrc->asSrc[0], 
				 bySrcMod, 
				 &sC10Arg, 
				 uUsedChansMask,
				 IMG_FALSE, 
				 IMG_FALSE,
				 psSrc->asSrc[0].eFormat);

	/* Pack the sources to the temporary f16 registers */
	{
		IMG_UINT32 uIdx;

		/* 
		   Convert the source of the input instruction 
		   and pack to f16 format.
		*/

		/* Pack the inputs to the temporaries */
		for (uIdx = 0; uIdx < uNumComps; uIdx ++)
		{
			IMG_UINT32 uComp = ConvertInputChannelToIntermediate(psState, uIdx);
			IMG_UINT32 uReg = uIdx / uChansPerDest;
			IMG_UINT32 uHalf = (uIdx % uChansPerDest) * 2;

			psPackInst = AllocateInst(psState, IMG_NULL);
			SetOpcode(psState, psPackInst, IUNPCKF16C10);
			psPackInst->u.psPck->bScale = IMG_TRUE;

			psPackInst->auDestMask[0] = (1U << (uHalf + 1)) | (1U << uHalf);
			psPackInst->asDest[0] = asArg[uReg];

			/* Get the source channel, putting it into the pack arguments */
			psPackInst->asArg[0] = sC10Arg;
			SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, uComp);

			psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
			psPackInst->asArg[1].uNumber = 0;

			AppendInst(psState, psCodeBlock, psPackInst);
		}
	}
	
	/* Emit the normalise instruction */
	EmitNormaliseF16(psState, 
					 psCodeBlock, 
					 &sDestReg, 
					 asArg,
					 uUsedChansMask,
					 bVec4, 
					 psSrc->uPredicate,
					 bSrcModNegate,
					 bSrcModAbsolute);

	/* Get the destination */
	GetDestinationC10(psState, &psSrc->sDest, &sDestReg);

	/* 
	   Unpack the result 
	*/

	/* Pack the result of the normalise into the destination */
	for (uCtr = 0; uCtr < uNumComps; uCtr ++)
	{
		IMG_UINT32 uReg = uCtr / uChansPerDest;
		IMG_UINT32 uChan = uCtr % uChansPerDest;

		if (!(psSrc->sDest.u.byMask & (1U << uCtr)))
			continue;

		psPackInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psPackInst, IPCKC10F16);
		psPackInst->u.psPck->bScale = IMG_TRUE;
		psPackInst->auDestMask[0] = (1U << ConvertInputChannelToIntermediate(psState, uCtr));

		psPackInst->asDest[0] = sDestReg;

		psPackInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
		psPackInst->asArg[0].uNumber += uTempDestNum + uReg;
		SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, uChan * 2);
		psPackInst->asArg[0].eFmt = UF_REGFORMAT_F16;

		psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
		psPackInst->asArg[1].eFmt = UF_REGFORMAT_F16;

		/* Set the predicate */
		GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);

		AppendInst(psState, psCodeBlock, psPackInst);
	}

	/* 
	   Any channels which aren't explicitly written take the value of
	   the last written channel.
	*/
	for ( /* skip */; uCtr < uNumChans; uCtr ++)
	{
		IMG_UINT32 uLastChan = uNumComps - 1;
		IMG_UINT32 uReg = uLastChan / uChansPerDest;
		IMG_UINT32 uChan = uLastChan % uChansPerDest;

		if (!(psSrc->sDest.u.byMask & (1U << uCtr)))
			continue;

		psPackInst = AllocateInst(psState, IMG_NULL);
		SetOpcode(psState, psPackInst, IPCKC10F16);
		psPackInst->auDestMask[0] = (1U << ConvertInputChannelToIntermediate(psState, uCtr));

		psPackInst->asDest[0] = sDestReg;

		psPackInst->asArg[0].uType = USEASM_REGTYPE_TEMP;
		psPackInst->asArg[0].uNumber += uTempDestNum + uReg;
		SetPCKComponent(psState, psPackInst, 0 /* uArgIdx */, (uChan * 2));
		psPackInst->asArg[0].eFmt = UF_REGFORMAT_F16;

		psPackInst->asArg[1].uType = USEASM_REGTYPE_IMMEDIATE;
		psPackInst->asArg[1].eFmt = UF_REGFORMAT_F16;

		/* Set the predicate */
		GetInputPredicateInst(psState, psPackInst, psSrc->uPredicate, uChan);

		AppendInst(psState, psCodeBlock, psPackInst);
	}
}
#endif /* defined(SUPPORT_SGX531) || defined(SUPPORT_SGX540) || defined(SUPPORT_SGX541) */

IMG_INTERNAL 
PCODEBLOCK ConvertInstToIntermediateC10(PINTERMEDIATE_STATE psState, 
									  	PCODEBLOCK psCodeBlock, 
									  	PUNIFLEX_INST psSrc, 
									  	IMG_BOOL bConditional,
									  	IMG_BOOL bStaticCond)
/*****************************************************************************
 FUNCTION	: ConvertInstToIntermediate

 PURPOSE	: Convert an input instruction to the intermediate format.

 PARAMETERS	: psState			- Compiler state.
			  psCodeBlock		- Block to add the intermediate instructions to.
			  psSrc				- Instruction to convert.
			  bConditional		- Whether instruction is conditionally executed
			  bStaticCond		- Whether condition is static.

 RETURNS	: None.
*****************************************************************************/
{
	switch (psSrc->eOpCode)
	{
		/* Texture sampling instructions. */
		case UFOP_LD:
		case UFOP_LDB:
		case UFOP_LDD:
		case UFOP_LDL:
		case UFOP_LDP:
		case UFOP_LDPIFTC:
		case UFOP_LDC:
		case UFOP_LDCLZ:
		case UFOP_LD2DMS:
		case UFOP_LDGATHER4:
		{
			psCodeBlock = CHOOSE_USPBIN_OR_USCHW_FUNC(ConvertSamplerInstructionC10, 
													  (psState, psCodeBlock, psSrc, bConditional && !bStaticCond));
			break;
		}
		case UFOP_LDTILED:
		{
			#if defined(OUTPUT_USPBIN)
			if (psState->uFlags & USC_FLAGS_COMPILE_FOR_USPBIN)
			{
				UscFail(psState, UF_ERR_INVALID_OPCODE, "LDTILED not supported for USP Binary output.\n");
			}
			#endif /*  defined(OUTPUT_USPBIN) */
			#if defined(OUTPUT_USPBIN) && defined(OUTPUT_USCHW)
			else
			#endif /* defined(OUTPUT_USPBIN) && defined(OUTPUT_USCHW) */
			#if defined(OUTPUT_USCHW)
			{
				ConvertLoadTiledInstructionC10(psState, psCodeBlock, psSrc);
			}
			#endif /* defined(OUTPUT_USCHW) */

			break;
		}

		/* Scalar instructions. */
		case UFOP_RECIP:
		case UFOP_RSQRT:
		case UFOP_EXP:
		case UFOP_LOG:
		case UFOP_SQRT:
		{
			ConvertScalarInstructionC10(psState, psCodeBlock, psSrc);
			break;
		}

		/* Vector instructions. */
		case UFOP_ADD:
		case UFOP_MUL:
		case UFOP_MIN:
		case UFOP_MAX:
		{
			ConvertVectorTwoArgInstructionC10(psState, psCodeBlock, psSrc);
			break;
		}
		case UFOP_MAD:
		{
			ConvertMadInstructionC10(psState, psCodeBlock, psSrc);
			break;
		}
		case UFOP_LRP:
		{
			ConvertLrpInstructionC10(psState, psCodeBlock, psSrc);
			break;
		}
		case UFOP_FRC:
		case UFOP_DSX:
		case UFOP_DSY:
		{
			#if defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554)
			if (psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_VEC34)
			{
				ConvertFloatOnlyInstructionC10_Vec(psState, psCodeBlock, psSrc);
			}
			else
			#endif /* defined(SUPPORT_SGX543) || defined(SUPPORT_SGX544) || defined(SUPPORT_SGX554) */
			{
				ConvertFloatOnlyInstructionC10(psState, psCodeBlock, psSrc);
			}
			break;
		}
		case UFOP_MOV:
		{
			ConvertMoveInstructionC10(psState, psCodeBlock, psSrc);
			break;
		}

		/* Dot products. */
		case UFOP_DOT2ADD:
		case UFOP_DOT3:
		case UFOP_DOT4:
		case UFOP_DOT4_CP:
		{
			ConvertDotProductInstructionC10(psState, psCodeBlock, psSrc);
			break;
		}

		/* Vector comparison instructions. */
		case UFOP_CMP:
		case UFOP_CMPLT:
		{
			ConvertComparisonInstructionC10(psState, psCodeBlock, psSrc);
			break;
		}
		case UFOP_SETP:
		{
			IMG_UINT32	uChanOp;

			uChanOp = ((psSrc->asSrc[1].uNum & UFREG_COMPCHANOP_MASK) >>  UFREG_COMPCHANOP_SHIFT);
			if(uChanOp)
			{
				/* User can select only one predicate channel for ANDALL/ORALL operations */
				/* SETP with ANDALL/ORALL cannot be predicated now */
				if( (!g_abSingleBitSet[psSrc->sDest.u.byMask]) || (psSrc->uPredicate) )
				{
					imgabort();
				}
			}
			ConvertSetpInstructionC10(psState, psCodeBlock, psSrc);
			break;
		}

		/* LIT/EXPP/LOGP/DST are invalid at low precision */
		case UFOP_LIT:
		case UFOP_OGLLIT:
		case UFOP_EXPP:
		case UFOP_LOGP:
		case UFOP_DST:
		{
			imgabort();
			break;
		}

		/* Move to address register instruction. */
		case UFOP_MOVA_TRC:
		case UFOP_MOVA_RNE:
		{
			ConvertMovaInstructionC10(psState, psCodeBlock, psSrc);
			break;
		}

		/* Kill instruction. */
		case UFOP_KPLT:
		case UFOP_KPLE:
		{
			ConvertTexkillInstructionC10(psState, psCodeBlock, psSrc, bConditional);
			break;
		}

		#if defined(SUPPORT_SGX531) || defined(SUPPORT_SGX540) || defined(SUPPORT_SGX541)
		case UFOP_NRM:
		{
			ConvertNormaliseC10(psState, psCodeBlock, psSrc, IMG_FALSE);
			break;
		}
		#endif /* defined(SUPPORT_SGX531) || defined(SUPPORT_SGX540) || defined(SUPPORT_SGX541) */

		/* Macro instruction. */
		case UFOP_SINCOS: 
		{
			#if defined(SUPPORT_SGX545)
			if (psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_SQRT_SIN_COS)
			{
				ConvertSincosC10HWSupport(psState, psCodeBlock, psSrc);
			}
			else
			#endif /* defined(SUPPORT_SGX545) */
			{
				imgabort();
			}
			break;
		}

		/* Macro instruction. */
		case UFOP_SINCOS2: 
		{
			#if defined(SUPPORT_SGX545)
			if (psState->psTargetFeatures->ui32Flags & SGX_FEATURE_FLAGS_USE_SQRT_SIN_COS)
			{
				ConvertSincos2C10HWSupport(psState, psCodeBlock, psSrc);
			}
			else
			#endif /* defined(SUPPORT_SGX545) */
			{
				imgabort();
			}
			break;
		}

		case UFOP_NOP: break;

		default: imgabort();
	}
	return psCodeBlock;
}

/******************************************************************************
 End of file (icvt_c10.c)
******************************************************************************/
